Managing Published Releases

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the Python Reference bibliography.

A release on PyPI is permanent in one direction: files can be removed, never replaced. What maintainers can do after publication is limited and differs a lot in its effect on users. This page covers those actions as documented on 2026-10-22. The yanking behaviour was reproduced on Linux with pip 26.2.2 on CPython 3.14.6, against a local static index; the PyPI examples are read-only queries of PyPI’s public APIs; no release was yanked, deleted or archived on PyPI.

Yanking (PEP 592)

A yanked release stays on the index but installers skip it, unless it is the only release matching a pin with == or ===. That keeps existing lock files working while new installs avoid the bad release. On PyPI you yank whole releases (not single files) from the release management page, with an optional reason that installers show.

A static simple index with birdtally 0.1.0 and a yanked 0.1.1 (the PEP 503 link carries data-yanked="broken CSV parsing"):

pip install --dry-run --no-deps --index-url http://127.0.0.1:8085/simple/ birdtally
pip install --dry-run --no-deps --index-url http://127.0.0.1:8085/simple/ birdtally==0.1.1
pip install --dry-run --no-deps --index-url http://127.0.0.1:8085/simple/ "birdtally>=0.1.1"
Would install birdtally-0.1.0
WARNING: The candidate selected for download or install is a yanked version: 'birdtally' candidate (version 0.1.1 at http://127.0.0.1:8085/files/birdtally-0.1.1-py3-none-any.whl#sha256=b64d4d23… (from http://127.0.0.1:8085/simple/birdtally/) (requires-python:>=3.10))
Reason for being yanked: broken CSV parsing
Would install birdtally-0.1.1
ERROR: Ignored the following yanked versions: 0.1.1
ERROR: Could not find a version that satisfies the requirement birdtally>=0.1.1 (from versions: 0.1.0)
ERROR: No matching distribution found for birdtally>=0.1.1

The latest is 0.1.0 because 0.1.1 is yanked; the exact pin still gets 0.1.1, with a warning; a range does not. pip’s --report marks the choice: "is_yanked": true for the pinned install. On PyPI, the JSON simple API exposes the same flag per file, for example for requests:

curl -s -H "Accept: application/vnd.pypi.simple.v1+json" https://pypi.org/simple/requests/
('requests-2.32.0-py3-none-any.whl', 'Yanked due to conflicts with CVE-2024-35195 mitigation')
('requests-2.32.0.tar.gz', 'Yanked due to conflicts with CVE-2024-35195 mitigation')
…

(the yanked field of each file, extracted). Yank a release that is broken or uninstallable, that breaks its compatibility promise by accident, or that has a security vulnerability; then publish a fixed release. Yanking does not free storage.

Deleting

Deleting a file, a release or a project is permanent and irreversible, without exception: PyPI’s administrators cannot restore it. A deleted project’s name becomes free for anyone to register, and deleted filenames can never be uploaded again. Deletion breaks every pinned install of those versions. Prefer yanking for a bad release and archiving for an abandoned project; delete only what must not be distributed at all (a leaked secret, files published by mistake), and rotate the secret anyway.

Archiving, quarantine and status markers (PEP 792)

Status Who sets it, since Effect

active

default

Uploads and downloads allowed.

archived

owners, 2025-01-30

No new uploads; existing files still installable; hidden from search. For projects that will receive no more updates.

quarantined

PyPI administrators, 2024-12-30

Not installable and not modifiable while PyPI reviews suspected malware or abuse; a single release can be quarantined.

deprecated

(specified)

Like active; installers may warn that the project is obsolete.

PEP 792 (statuses in the index APIs, 2025-08-14) puts the status in the simple API, where installers can read it:

{'meta': {'_last-serial': 25862117, 'api-version': '1.4'}, 'name': 'sampleproject', 'project-status': {'status': 'active'}}

(the JSON simple page of sampleproject without its file list).

Adding files to an existing release

Since 2026-07-22 PyPI refuses new files for a release that is more than 14 days old; the PyPI blog adds that users "should not yet rely" on this as defined semantics. A wheel for a new Python version or platform (say cp315 wheels for an extension built before 3.15 existed) therefore needs a new release, typically a post-release (1.4.0.post1) with the same code, built and uploaded together.

Storage limits

PyPI allows 100 MB per file and 10 GB per project by default. Free space by deleting old releases or individual files (with the consequences above); yanking does not help. Larger limits are requested through PyPI’s support tracker, per index (PyPI and TestPyPI separately), after a release under the limit exists. Projects owned by an organization are transferred or deleted by the organization’s owners from the organization’s project settings.

Download statistics (not run here)

PyPI logs every download to the public BigQuery table bigquery-public-data.pypi.file_downloads (one row per download with timestamp, file.project, file.version, details.installer.name, details.python and more). A Google Cloud project with the BigQuery API enabled can query it within the free tier:

#standardSQL
SELECT file.version, COUNT(*) AS downloads
FROM `bigquery-public-data.pypi.file_downloads`
WHERE file.project = 'birdtally'
  AND details.installer.name = 'pip'
  AND DATE(timestamp) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY) AND CURRENT_DATE()
GROUP BY file.version
ORDER BY downloads DESC

Caveats: downloads are not users (CI runs and mirrors dominate many counts), mirrors and caches hide downloads, and data before 2018-07-26 is under-reported. Tools: pypinfo (a command-line front end), pandas-gbq (query into a DataFrame), the google-cloud-bigquery client, and ClickPy (a public ClickHouse-based dashboard of the same data).