browser-download-filename
Name downloaded files the way Chrome does. A pure-Python port of the Content-Disposition parser and the download naming rules of Chromium, the open-source core of Chrome, Edge and other browsers.
HTTP clients hand you a response, not a file name. The usual ways to get one
(the standard library's email module, RFC 6266 parsers on PyPI) disagree
with browsers on headers that real servers send: an ASCII fallback before
filename*, raw UTF-8, percent-encoded names, language tags, semicolons
inside quotes. This package gives the name Chrome gives.
Features
- Chromium's answer — the header parser, the charset decoders and the file name sanitization are ports of Chromium's code at a pinned revision, tested with Chromium's own unit test cases. CI downloads more than 800 cases with a real Chromium and requires the same name for each.
- Bytes or str — pass the header as the bytes on the wire, or as the str
your HTTP library made of them; the Latin-1 strs of requests, urllib3 and
http.clientand the surrogate-escaped strs of aiohttp are mapped back to the bytes. - Never raises on a malformed header — it returns what Chromium makes of it.
- Safe names — the result is a single file name, never empty, with path
separators, control characters and other characters that file systems
reject replaced.
platform="windows"adds Windows' rules for reserved names, trailing dots and spaces, and shortcut extensions. - No dependencies — pure Python, one wheel for every platform: CPython 3.11+ and PyPy.
Install
pip install browser-download-filename # or: uv add browser-download-filename
Usage
>>> from browser_download_filename import parse_content_disposition, suggested_filename
>>> header = b"attachment; filename=report.pdf; filename*=UTF-8''%E5%A0%B1%E5%91%8A.pdf"
>>> suggested_filename("https://example.com/download?id=42", header)
'報告.pdf'
>>> suggested_filename("https://example.com/files/r%C3%A9sum%C3%A9.pdf")
'résumé.pdf'
>>> parse_content_disposition('attachment; filename="a;b;c.txt";')
ContentDisposition(type='attachment', filename='a;b;c.txt')
suggested_filename takes the final URL of the response (after redirects) and
the Content-Disposition header, and returns the name Chrome reports to DevTools
and Playwright as the download's suggested file name:
import requests
from browser_download_filename import suggested_filename
response = requests.get(url)
header = response.headers.get("Content-Disposition")
name = suggested_filename(
response.url,
header.encode("latin-1") if header else None, # the bytes on the wire
mime_type=response.headers.get("Content-Type"),
)
Documentation
Full documentation (English / 正體中文), including usage with requests, httpx, aiohttp and urllib, the options, how Chrome, Firefox and Safari differ, how the package is checked against Chromium, the API reference and a changelog: https://birdhackor.github.io/browser-download-filename/
License
Licensed under either of MIT or Apache-2.0 at your option.
The package contains code ported from Chromium (BSD-3-Clause) and tables
generated from ICU and the WHATWG Encoding Standard (Unicode-3.0 and
BSD-3-Clause), so the distributions as a whole are under
(MIT OR Apache-2.0) AND BSD-3-Clause AND Unicode-3.0; see
THIRD-PARTY-LICENSES.
Metadata
Release files for browser-download-filename 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| browser_download_filename-0.1.0.tar.gz | 74.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| browser_download_filename-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 116.9 kB
Release files / browser_download_filename-0.1.0.tar.gz
| Download URL | browser_download_filename-0.1.0.tar.gz |
|---|---|
| Size | 74.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1e456fb78e4232902b552188ee4c14f0cfeb5a12a65fc5030274474266b484a0
|
|
BLAKE2b-256 checksum How to use checksums |
e6667ac0aa45d6a12f5bba3621efe73d7eb50ec92912a4885e51e63ca8af4945
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency logRelease files / browser_download_filename-0.1.0-py3-none-any.whl
| Download URL | browser_download_filename-0.1.0-py3-none-any.whl |
|---|---|
| Size | 42.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8c8805a77049775e1170ba6ec6bfd0be327eaaa98ce777f712a6e7f81cb8fd4d
|
|
BLAKE2b-256 checksum How to use checksums |
7f1885bb40234b9f37b5107274410af78f174be39ad1c1a375c145bdbfe041fe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency log