Integration guide

We provide multiple APIs to help you integrate with PyPI; see API reference.

Many tools already integrate with PyPI, uploading packages or retrieving data; see the Python Packaging Guide’s tool recommendations.

Migrating to the new PyPI

Warehouse has now replaced the legacy PyPI site that was deployed at If your site/service used to link or upload to, it may continue to work due to redirects, but you should use instead.

You should also watch our status page and subscribe to the PyPI announcement list (low-traffic) to find out about future changes.

Here are some tips.


{name} is the name of the package as represented in the URL; for, you’d insert arrow wherever you see {name}.

  • If your client correctly follows redirects, you can replace in your links with and everything should just work. For instance, the project detail page{name} (with or without a trailing slash) redirects to{name}/.

  • Shorter URL:{name}/ will redirect to{name}/.

  • All APIs: access is HTTPS-only (changed in October 2017). And honors an Accept-Encoding: gzip header, whereas ignored it.

  • JSON API:{name}/json returns the expected JSON response directly. See JSON API.

  • XML-RPC API: See Changes to XMLRPC API. Will be deprecated in the future (no specific end date set yet); switch to the RSS or JSON APIs. If you depend on an XML-RPC call that our other APIs do not support, tell us.

  • Packages/updates RSS feeds: redirects to, and redirects to See Feeds for descriptions. The data differs from the legacy feed data because the new feeds are standards-compliant and fix inaccuracies in the publication date.

  • Documentation upload: Users can no longer use doc_upload in the API to upload documentation ZIP files, separate from packages, to be hosted at (discussion).

  • User-Agent Filtering: Some client user agents were filtered to always use, a temporary deployment of the legacy PyPI codebase, regardless of brownouts or redirects, in order to give them extra time to migrate. On 30 April 2018, was shut down, so all clients use regardless of their User-Agent.

  • Subscribe to the PyPI announcement list (low-traffic).

If you’re a PyPI end user or packager looking to migrate to the new PyPI, see the official Python Packaging User Guide on migrating to PyPI.

Querying PyPI for Package URLs

When copying a download link from, you get a URL with a random hash value in it.

This hash value is calculated from the checksum of the file. The URLs on PyPI for individual files are static and do not change.

Official guidance

Query PyPI’s JSON API to determine where to download files from.

Predictable URLs

You can use our conveyor service to fetch this file, which exists for cases where using the API is impractical or impossible. This is for example the case for Linux package maintainers, as package build scripts or package metadata expect static URLs in some cases.

URLs can be constructed as follows, with wheel file names following PEP 491#file-name-convention.

host = ''

def source_url(name, version):
    return f'{host}/packages/source/{name[0]}/{name}/{name}-{version}.tar.gz'

def wheel_url(name, version, build_tag, python_tag, abi_tag, platform_tag):
    wheel_parts = {
        tag: re.sub(r'[^\w\d.]+', '_', part, re.UNICODE)
        for tag, part in locals().items()
    wheel_parts['optional_build_tag'] = f'-{wheel_parts["build_tag"]}' if build_tag else ''
    filename = '{name}-{version}{optional_build_tag}-{python_tag}-{abi_tag}-{platform_tag}.whl'\
    return f'{host}/packages/{python_tag}/{name[0]}/{name}/{filename}'


$ curl -I
HTTP/2 302

As you’ll note, it is just a redirect to the canonical file.