content-types v0.5.7
  • API Reference
  • Changelog

Skills

A skill is a package of structured files that teaches an AI coding agent how to work with a specific tool or framework. The skill below was generated by Great Docs from this project’s documentation. Install it in your agent and it will be able to run commands, edit configuration, write content, and troubleshoot problems without step-by-step guidance from you.

Any agent — install with npx:

npx skills add https://mkennedy.codes/docs/content-types/

Codex / OpenCode

Tell the agent:
Fetch the skill file at https://mkennedy.codes/docs/content-types/skill.md and follow the instructions.

Manual — download the skill file:

curl -O https://mkennedy.codes/docs/content-types/skill.md

Or browse the SKILL.md file.

SKILL.md

---
name: content-types
description: >
  A library to map file extensions to content types and vice versa. Use when writing Python code that uses the content_types package.
license: MIT
compatibility: Requires Python >=3.10.
---

# content-types

A library to map file extensions to content types and vice versa.

## Installation

```bash
pip install content-types
```

## API overview

### Forward lookup

Map a filename, bare extension, Path, or URL to its MIME / content type.

- `get_content_type`: Return the most specific, commonly accepted MIME type for a filename or extension

### Reverse lookup

Map a MIME / content type back to its file extension(s) — the inverse of get_content_type.

- `guess_extension`: Return the canonical file extension for a MIME / content type
- `guess_all_extensions`: Return every known file extension for a MIME / content type, canonical first

### Mapping data

The underlying extension -> content-type table (364 entries; keys have no leading dot).

- `EXTENSION_TO_CONTENT_TYPE`: dict() -> new empty dictionary

### Shortcut constants

Precomputed content types for very common formats, exposed as module-level attributes.

- `webp`: str(object='') -> str
- `png`: str(object='') -> str
- `jpg`: str(object='') -> str
- `mp3`: str(object='') -> str
- `json`: str(object='') -> str
- `pdf`: str(object='') -> str
- `zip`: str(object='') -> str
- `xml`: str(object='') -> str
- `csv`: str(object='') -> str
- `md`: str(object='') -> str
- `parquet`: str(object='') -> str
- `ipynb`: str(object='') -> str
- `pkl`: str(object='') -> str
- `yaml`: str(object='') -> str
- `toml`: str(object='') -> str
- `sqlite`: str(object='') -> str

## End-to-end wiring

The core use case: you know a filename (often for a remote/S3 object you don't want to download) and need its content type — and sometimes the reverse, turning an HTTP `Content-Type` header back into a file extension. The library never opens or sniffs file bytes; everything is extension lookup.

```python
from pathlib import Path
import boto3
import content_types

s3 = boto3.client('s3')

# Upload with the correct Content-Type (S3 defaults to binary/octet-stream otherwise)
local = Path('reports/summary.pdf')
s3.upload_file(
    str(local), 'my-bucket', f'reports/{local.name}',
    ExtraArgs={'ContentType': content_types.get_content_type(local)},  # 'application/pdf'
)

# Reverse: pick a filename extension from a response's Content-Type header
import httpx
resp = httpx.get('https://example.com/download/item')
ext = content_types.guess_extension(resp.headers['content-type'])  # e.g. '.png' — params like '; charset=...' are stripped
if ext:
    Path(f'downloaded{ext}').write_bytes(resp.content)
```

## It is not `mimetypes` — the API and the answers differ

Do not guess this API from the standard library `mimetypes` module. The forward function is `get_content_type()` (not `guess_type()`, and it returns the type string alone, not a `(type, encoding)` tuple). `guess_extension()`/`guess_all_extensions()` exist in both, but this library's versions accept full header values with parameters (`'text/html; charset=utf-8'`), resolve legacy alias spellings (`text/json`, `image/jpg`, `audio/mp3`, `application/x-zip-compressed`, `text/xml`, `application/javascript` all resolve to their canonical types), and return the canonical extension first — `text/html` → `.html` (stdlib often says `.htm`), `image/jpeg` → `.jpg`.

The answers are deliberately modernized too: `.xml` → `application/xml`, `.js` → `text/javascript`, `.yaml`/`.yml` → `application/yaml` (RFC 9512, not the legacy `text/yaml`), `.md` → `text/markdown`, plus ~264 extensions the stdlib is missing entirely (`.webp`, `.parquet`, `.ipynb`, `.woff2`, `.heic`, `.mkv`, ...).

## Input shapes and edge cases for `get_content_type()`

All of these work: a filename (`'photo.jpg'`), a full path (`'images/photo.jpg'`), a bare extension (`'jpg'` or `'.jpg'`), a `pathlib.Path`, or a URL — query strings (`?...`) and fragments (`#...`) are stripped first. Matching is case-insensitive.

Compound extensions use the **last** segment only: `archive.tar.gz` → `application/gzip` (there is no special `tar.gz` handling). Extension-less names (`Makefile`, `.gitignore`, `''`) are unknown and get the fallback.

## Unknown extensions: `treat_as_binary` vs `fallback`

Three distinct behaviors, and `fallback` wins over `treat_as_binary` when both are given:

```python
content_types.get_content_type('x.xyz')                          # 'application/octet-stream' (default)
content_types.get_content_type('x.xyz', treat_as_binary=False)   # 'text/plain'
content_types.get_content_type('x.xyz', fallback='application/x-custom')  # your placeholder
content_types.get_content_type('x.xyz', fallback=None)           # None — branch on a miss
```

`fallback=None` is meaningful, not the default: the parameter defaults to a private sentinel, so omitting `fallback` keeps the `treat_as_binary` behavior while an explicit `None` returns `None` for unknowns. Passing `None` as the *filename* raises `TypeError`; so does passing `None` to the reverse-lookup functions (which signal unknown types with `None` / `[]` instead).

## Keys in the mapping table have no leading dot

`EXTENSION_TO_CONTENT_TYPE` keys are bare lowercase extensions: `EXTENSION_TO_CONTENT_TYPE['jpg']`, never `['.jpg']`. By contrast, `guess_extension()`/`guess_all_extensions()` return extensions **with** the dot by default (`'.pdf'`) — pass `with_dot=False` for bare ones.

## Shortcut constants are plain strings

Sixteen precomputed module-level constants (`webp`, `png`, `jpg`, `mp3`, `json`, `pdf`, `zip`, `xml`, `csv`, `md`, `parquet`, `ipynb`, `pkl`, `yaml`, `toml`, `sqlite`) are just the looked-up strings, ready for headers: `{'Content-Type': content_types.json}`. Watch the names when using `from content_types import ...` — `json`, `zip`, and `csv` shadow the stdlib module / builtin; prefer `import content_types` and attribute access.

## CLI

The package installs a `content-types` console script that does forward lookup only:

```bash
$ content-types photo.jpg
image/jpeg
$ content-types .webp
image/webp
```

## Fetching the docs as Markdown

Every page on the documentation site has a plain-Markdown twin: swap the `.html` extension for `.md` to get token-efficient source without the site chrome. For example https://mkennedy.codes/docs/content-types/reference/get_content_type.html is also available at https://mkennedy.codes/docs/content-types/reference/get_content_type.md. Prefer the `.md` form when reading these docs programmatically.


## Resources

- [Full documentation](https://mkennedy.codes/docs/content-types/)
- [llms.txt](llms.txt) — Indexed API reference for LLMs
- [llms-full.txt](llms-full.txt) — Comprehensive documentation for LLMs
- [Source code](https://github.com/mikeckennedy/content-types)

Developed by Michael Kennedy.
Site created with Great Docs.