PyPI: The HTML representation of the index API is frozen

woodruffw1 pts0 comments

The HTML representation of the index API is now frozen - The Python Package Index Blog

Skip to content

Initializing search

GitHub

Authors

The HTML representation of the index API is now frozen

PyPI has adopted PEP 833, which "freezes" the<br>HTML representation of the index API, which is also<br>sometimes called the "simple API" or the "simple repository API."

New packages and releases will continue to appear in the HTML<br>representation, meaning this has no breaking implications<br>for downstream index consumers.

However, future standardization and development efforts will focus<br>on the JSON representation, and downstreams that consume only the HTML<br>representation are strongly encouraged to transition to the JSON<br>representation to ensure access to the latest and greatest index features.

Background

As the name suggests, PyPI's primary responsibility is serving a<br>package index. Installers (like pip and uv) consume this<br>index as part of resolving and installing dependencies.

For historical reasons, there are two different standard representations<br>of a Python packaging index:

The HTML representation, which predates standardization, and was<br>retroactively standardized with PEP 503.

The HTML index is essentially a bare-bones version of the<br>human-readable index that PyPI once served, back before PyPI<br>was a resource that installers automatically retrieved packages<br>from. It's that old!

The JSON representation, which was standardized with PEP 691.

Unlike the HTML representation, the JSON representation was designed<br>from the ground-up to be useful to machine clients, rather than<br>humans.

The two representations are more or less1 coextensive in terms of<br>serving the information that installers care about. This is intentional:<br>efforts to extend the simple index over the years have worked hard<br>to put that state into both representations.

Doing so with the HTML representation is often unwieldy, as<br>metadata that naturally fits JSON's object model needs to be<br>shoehorned into nooks and crannies (mainly HTML attributes and new tags)<br>that won't interfere with pre-existing assumptions about the<br>HTML's shape.

Unfortunately, that shoehorning process is has become harder over time:

Many consumers have made suboptimal, unsound assumptions about<br>the shape of shape of PyPI's HTML representation. More<br>precisely: they go beyond assuming the basic shape of the HTML,<br>and actually make assumptions about semantically irrelevant<br>aspects like whitespace, attribute order, &c.

This makes even "shape preserving" changes to the HTML representation<br>fraught.

By contrast, consumers of the JSON representation don't generally<br>encounter these issues. Some of that is probably a function of<br>the JSON representation being newer, but a large part is<br>likely because, unlike HTML, users don't find themselves open-coding<br>a JSON parser in high-level languages.

Because the fundamental shape of the HTML representation can't be changed,<br>adding new pieces of metadata to it becomes an exercise in creative<br>munging: things that are natural to express as object members in<br>JSON need to be shoehorned into new, flat tags or HTML<br>attributes in the HTML representation.

PEP 792 is a good example of this. Compare the JSON representation:

"meta": {<br>"api-version": "1.4"<br>},<br>"project-status": {<br>"status": "quarantined",<br>"reason": "the project is haunted"

...to the HTML one:

meta name="pypi:repository-version" content="1.4"><br>meta name="pypi:project-status" content="quarantined"><br>meta name="pypi:project-status-reason" content="the project is haunted">

This may not seem so bad in isolation, but keep in mind that this<br>flattening and munging needs to happen for every single<br>new addition to the index.

Even when we do successfully shoehorn features into the<br>HTML representation (on paper, and on PyPI), it often<br>doesn't matter to users : users are bifurcated between adoption<br>of the JSON representation (which doesn't have these issues)<br>and third-party (often private) indices that only<br>implement the absolute bare minimum required in PEP 503.

As a result, even when we do update the HTML representation,<br>users rarely benefit from it.

"Freezing" the HTML representation is our way of acknowledging this<br>situation. It's our way of saying that we can't2 deprecate the<br>HTML representation, but that we don't want to keep extending it<br>given how lopsided the tradeoffs are.

Do I have to do anything?

No!

The HTML representation is not going away , and will not<br>go "stale" in terms of content updates. "Freezing" means that<br>Python packaging as a whole has made a policy decision<br>to not continue to munge features into its structure.

In other words: the HTML representation will continue to be served by PyPI<br>for the foreseeable future, but Python packaging as a whole<br>will no longer prioritize attempting to shoe-horn new pieces<br>of metadata into its relatively inflexible HTML structure.

The longer answers:

If you're an "individual" downstream package consumer (e.g., a<br>user who installs...

html representation index pypi json shape

Related Articles