# Pygments: the syntax highlighter that thousands of docs pipelines depend on

> A generic syntax highlighter written in Python, covering over 500 languages and text formats. The interesting parts are the lexer architecture, the security warning in its own README, and a plugin mechanism that now survives only as an empty extra.

**pygments/pygments** — Pygments is a generic syntax highlighter written in Python

- Repository: https://github.com/pygments/pygments
- Website: http://pygments.org/
- Stars: 2,213 · Forks: 909
- Language: Python
- License: BSD-2-Clause
- Published: 2026-10-08 · Updated: 2026-10-08 · Language: en
- Canonical page: https://hysenlabs.com/projects/pygments-pygments

## A library first, a service never

Pygments describes itself as a generic syntax highlighter written in Python that supports over 500 languages and text formats, for use in code hosting, forums, wikis or other applications that need to prettify source code. Read that carefully, because it sets the boundary of the project. There is no server here, no daemon, no configuration file to deploy. What ships is a package that another program imports and calls, and the list of consumers the README names is a list of things that will import it.

That shape has consequences for how you evaluate it. A highlighter that runs as a service asks you to think about processes, ports and queues. A highlighter that runs as a library only asks whether it produces the token stream you want and whether it stays inside your latency budget. The repository tree matches that reading: a `pygments/` package directory, a `tests/` directory, a `doc/` directory, plus the usual project furniture in `pyproject.toml`, `tox.ini`, `requirements.txt` and a `scripts/` directory.

The metadata lists the project language as Python and the topics as `python` and `syntax-highlighting`, and the repository is not archived with the last push on 2026-09-27. The package metadata in `pyproject.toml` classifies the project as `Development Status :: 6 - Mature` and requires Python 3.9 or newer, with classifiers running ahead of that to 3.15.

## Installing published releases or a checkout

The README gives two install paths and nothing else, which is how you can tell this is a mature project rather than one still deciding how it wants to be distributed. Published versions come from PyPI, and a checkout installs in editable mode for development:

```bash
pip install Pygments
```

```bash
pip install -e .
```

There is no extra setup step, no lexer registration, and no manifest to write. The optional dependency list in `pyproject.toml` is short enough to read in full: `plugins = [] # kept for backwards compatibility` and `windows-terminal = ["colorama >= 0.4.6"]`.

That first line is worth pausing on, because it is the clearest statement in the repository about a design decision. Pygments historically accepted third-party lexers registered through Python entry points. The extra still exists so that an existing `pip install Pygments[plugins]` line keeps working, but it now resolves to an empty list. Extensions that used to arrive through packaging have to be imported explicitly instead.

For building the documentation from a checkout, the README points at tox:

```bash
tox -e doc
```

The same section explains that the demo page is excluded by default because it needs Docker and Pyodide, and that `tox -e web-doc` builds it. Serving the result needs Python's own HTTP server rather than a documentation plugin:

```bash
python3 -m http.server --directory doc/_build/html
```

## What the release notes reveal about lexer design

The README does not explain the internal architecture, so the release notes are where the design becomes visible. Version 2.21.0, published on 2026-08-17, lists new lexers for BitBake, Caddyfile, CEL and PureScript, then a long list of updates to existing ones. Two entries in that list describe how lexers relate to each other rather than what colours they produce.

The CUDA entry says the lexer was changed to derive from the C++ lexer instead of C, specifically so that constructs such as `template`, `class` and `namespace` get highlighted. The ComponentPascal fix in version 2.20.0 mentions `analyse_text`, which is the hook a lexer uses to inspect the source and guess whether it should claim a particular stream. Between them those two notes describe a system where lexers inherit from one another and where disambiguation is content based rather than purely filename based.

Everything else in those releases is keyword and operator work, and there is a lot of it: C23 and C++26 attributes, C# interpolated verbatim string prefixes in either `$@` or `@$` order, Java module keywords, Haskell escape sequences inside character literals, LLVM C-style comments. This is the real cost model of a highlighter with broad coverage. Supporting a language means tracking its releases, and the changelog reads like a slow, continuous drip of language-version updates rather than a series of architectural changes.

One naming change is easy to miss and easy to trip over: version 2.20.0 records that Coq was renamed to Rocq, with two issue numbers attached. If you hard-code lexer names in a stylesheet or a mapping table, upstream renames like this one are the thing that breaks the build, not upgrades to Pygments itself.

## Why the README leads with a denial of service warning

Most READMEs lead with features. This one has a section titled `Security considerations` that says Pygments provides no guarantees on execution time, and that arbitrary user input should be treated accordingly. The argument is specific rather than hand-wavy: some regular expressions can result in catastrophic backtracking, other bugs such as incorrect matchers cause similar problems, and there is no way to find them automatically.

The mitigation advice is equally concrete, and it is an architecture recommendation rather than a code patch. Terminate the Pygments process after a reasonably short timeout, because in general Pygments should take seconds at most for reasonably sized input. Limit the number of concurrent Pygments processes to avoid oversubscription. In other words, if you are exposing highlighting to strangers, run it somewhere you can kill.

The project is candid about the limits of its own defences and names the defences it does have: extensive unit tests, automated randomized testing, and testing by OSS-Fuzz. It also states the triage policy plainly, saying the authors treat any bug resulting in long processing times with high priority because it is the kind of thing fixed in a patch release.

The release history backs the claim without settling it. Version 2.20.0 fixed catastrophic backtracking in the archetype lexer's GUID and ID patterns, in Devicetree, and in Lua(u). Three fixes in one release is a real record of the bug class, and it is also a reminder that fixes arrive per lexer rather than as a structural change to how matching works.

## Comparing the README against the package metadata

Two small inconsistencies are worth knowing about because they are the kind of thing that sends someone looking in the wrong place.

The first is the documentation URL. The README says the documentation can be found online at `https://pygments.org/`, and `pyproject.toml` lists `Homepage = "https://pygments.org"` with `Documentation = "https://pygments.org/docs"`. The repository homepage field, however, is recorded as `http://pygments.org/` without the scheme upgrade. All three point at the same site and the difference has no practical effect on a reader, but if you are generating a link from a metadata field, expect the older form.

The second is how the project describes itself. The repository description calls Pygments a generic syntax highlighter written in Python, while `pyproject.toml` describes it as a syntax highlighting package written in Python and comments that PyPI should get the shorter description from `description.rst` rather than from `README.rst`. The `description.rst` file in the tree is that separate short form. Again the two are not in conflict about behaviour, only about which blurb goes where.

Neither of these tells you anything you cannot get from the other. What the pair does tell you is that the README is written for people who already know the package, while the metadata is written for people deciding whether to install it, and the project maintains both on purpose.

## Where to look beyond the README for lexer coverage

The README is deliberately short, and the questions it leaves open are the ones that actually matter when you are choosing a highlighter. It does not list the supported languages. It does not tell you which style names are available, whether a style supports background colours, or how output is escaped. It points to pygments.org and to the contributing instructions, and stops.

That is a reasonable division of labour for a library this widely used, but it means the decision you are making cannot be made from the repository page. The supported-language question in particular has to be answered on the hosted documentation, because the answer changes with every release and the README only claims a count.

The repository is still worth reading for the parts the docs cannot tell you. The presence of `tests/` and `external/` suggests the fixtures and data files that back the lexer tests, and `scripts/` holds the maintenance tooling. Version history is the best signal of pace: 2.19.2 shipped on 2025-06-21, 2.20.0 on 2026-03-29, and 2.21.0 on 2026-08-17, so the project moves on a multi-month cadence with patch releases in between.

Maintenance is handled by Georg Brandl, with Matthias Chajdas and Jean Abou-Samra named alongside him in both the README and `pyproject.toml`, and Armin Ronacher, the Pocoo team and Tim Hatch credited for many lexers and fixes. The code is distributed under the BSD 2-clause license, and contributors submitting pull requests are required to agree that their contributions can go under that same license.

## Conclusion

Pygments is a good fit when your input is code you trust and you want highlighting that behaves the same on every platform, especially if you already have Sphinx, a Python web framework, or a documentation toolchain that pulls it in transitively. It is the wrong choice when the highlighting happens inside a request path reachable by strangers, because the project's own documentation says execution time is unbounded and recommends killing the process on a timeout. Start with `pip install Pygments`, check the style names in the `pygments/` package before committing to a CSS theme, and if you are rendering user uploads, put a time limit and a concurrency cap around the call rather than trusting the lexer to return.

## FAQ

### What languages are supported by Pygments?

The README claims support for over 500 languages and text formats, and the exact list lives in the hosted documentation at pygments.org rather than in the repository. Recent releases add lexers one at a time, with version 2.21.0 adding BitBake, Caddyfile, CEL and PureScript.

### How do I install Pygments and call it from Python?

The README documents `pip install Pygments` for published releases and `pip install -e .` for a checkout. There is no configuration step; Pygments is imported as a library by whatever application needs highlighted output.

### Is it safe to highlight untrusted input with Pygments?

The project says it provides no guarantees on execution time and that some inputs can cause very long runs or heavy memory use. Its own recommendation is to terminate the Pygments process after a short timeout and to limit how many Pygments processes run concurrently.

### Why is the Pygments plugins extra still there if it is empty?

The `pyproject.toml` optional dependency list contains `plugins = [] # kept for backwards compatibility`. The extra is preserved so existing install commands keep working after lexer registration stopped relying on packaged entry points.

### What license is Pygments released under?

The BSD 2-clause license. The metadata records `BSD-2-Clause`, the README says the code is distributed under the BSD 2-clause license, and `pyproject.toml` lists `AUTHORS` and `LICENSE` as the license files.

## Sources

- [License: BSD-2-Clause](https://github.com/pygments/pygments/blob/master/LICENSE)
- [Project website](http://pygments.org/)
- [pygments/pygments on GitHub](https://github.com/pygments/pygments)
- [README](https://github.com/pygments/pygments/blob/master/README.md)
- [Releases](https://github.com/pygments/pygments/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pygments-pygments
