MIME Types Cheatsheet - Content-Type Reference

A wrong Content-Type is often the invisible cause of broken downloads, garbled pages and rejected uploads. Organized by file category, each media type maps to extensions, the correct Content-Type string and charset notes. Use it to configure Nginx mime.types, set response Content-Type in server code, and validate what a browser infers from the header. After reading you know why .wasm or .woff2 serves wrong and how to fix it.

Reference·47 commands·Last updated 2026-07-21
mimecontent-typehttp

Typical Use Case

For developers writing HTTP responses, serving static assets, and handling file upload and download. The MIME type decides how a browser disposes of a response: marked text/html it renders, marked application/octet-stream it downloads. This sheet groups 47 common types by category — text, image, audio and video, fonts, office documents, archives — plus three that are easy to miss: text/event-stream (SSE), application/wasm (WebAssembly) and application/ld+json (SEO structured data). File upload also depends on the multipart/form-data boundary rule.

Text Types 8

text/html
.html HTML document
text/css
.css Stylesheet
text/javascript
.js JavaScript
text/plain
.txt Plain text
text/xml
.xml XML document
text/csv
.csv CSV File
text/markdown
.md Markdown document
text/event-stream
Server-sent events (SSE) stream

Image Types 7

image/jpeg
.jpg/.jpeg JPEG image
image/png
.png PNG image (lossless)
image/gif
.gif GIF image (supports animation)
image/svg+xml
.svg SVG vector graphic
image/webp
.webp WebP image
image/avif
.avif AVIF image (next-generation compression)
image/x-icon
.ico Icon file

Audio/Video Types 7

audio/mpeg
.mp3 MP3 audio
audio/wav
.wav WAV audio
audio/ogg
.ogg OGG audio
audio/aac
.aac AAC audio
video/mp4
.mp4 MP4 video
video/webm
.webm WebM video
video/quicktime
.mov MOV video

Apps & Data Types 9

application/json
.json JSON data
application/xml
.xml XML data
application/javascript
.js JavaScript (legacy media type, prefer text/javascript)
application/octet-stream
Arbitrary binary stream (default download type)
application/x-www-form-urlencoded
Form submission (default HTML form encoding)
multipart/form-data
File upload in multipart forms
application/wasm
.wasm WebAssembly module
application/graphql
GraphQL request body
application/ld+json
JSON-LD structured data (SEO)

Document Types 6

application/pdf
.pdf PDF document
application/msword
.doc Legacy Word document
application/vnd.openxmlformats-officedocument.wordprocessingml.document
.docx Word document (Office Open XML)
application/vnd.ms-excel
.xls Legacy Excel spreadsheet
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
.xlsx Excel spreadsheet (Office Open XML)
application/vnd.openxmlformats-officedocument.presentationml.presentation
.pptx PowerPoint presentation

Compression Types 6

application/zip
.zip ZIP Compresspackage
application/gzip
.gz GZIP Compresspackage
application/x-tar
.tar TAR archive
application/x-bzip2
.bz2 BZIP2 Compresspackage
application/x-7z-compressed
.7z 7Z Compresspackage
application/x-rar-compressed
.rar RAR Compresspackage

Font Types 4

font/woff
.woff WOFF web font
font/woff2
.woff2 WOFF2 web font
font/ttf
.ttf TrueType font
font/otf
.otf OpenType font

Parameter matrix

ParameterEffectExample
Content-Type headerdecides whether a browser renders or downloads; get it wrong and the page becomes a filetext/html :: .html HTML document
text/* and image/* familiespick a type by family; text/event-stream is what SSE responses must usetext/event-stream :: server-sent events stream
application/octet-streamthe default binary type; using it forces a download instead of any renderingapplication/octet-stream :: binary stream (download by default)
multipart/form-datathe type for form uploads; the body is split by a boundary that must be declaredmultipart/form-data :: file upload
vnd.openxmlformats-* familyofficial type names for modern Office documents, coexisting with the old msword/vnd.ms-excel onesapplication/vnd.openxmlformats-officedocument.wordprocessingml.document :: .docx
font typesload fonts in @font-face preferring font/woff2, falling back to woff or ttffont/woff2 :: .woff2 WOFF2 font

Common pitfalls

SymptomAn API returns JSON and the browser pops up a save-file dialog.

CauseThe response header says application/octet-stream or omits Content-Type, so the browser treats it as binary.

FixSwitch to application/json and make sure Content-Type appears in the exposed CORS headers.

SymptomAn upload endpoint reports a missing boundary or the server cannot parse the file.

CauseA hand-written multipart/form-data header left out the boundary parameter, and the body lacks the matching delimiter.

FixDo not hand-write it: use FormData so the browser or framework generates the boundary.

SymptomAn SVG icon renders blank in the browser or opens as a standalone document.

Causeimage/svg+xml is an executable document type, so inline scripts inside it run.

FixStrip scripts from externally served SVG, or switch to PNG and font icons.

SymptomA downloaded .docx will not open and Office complains the format does not match the extension.

CauseA modern docx was labelled with the legacy application/msword, so the declared type disagrees with the real container.

FixPick the matching vnd.openxmlformats-officedocument.* type from this sheet instead of the old msword.

Troubleshooting

  1. 1Inspect the Content-Type a URL actually returns

    curl -sI https://example.com/app.js | grep -i content-type

    Compare against text/javascript from this sheet; a mismatch makes the browser download it.

  2. 2Infer a file type and compare it to this sheet

    file --mime-type data.json

    It prints application/json, matching the application/json entry here, so the request can proceed.

Command Examples

Detecting real file types with file --mime-type

file --mime-type package.json nuxt.config.ts

file inspects magic numbers rather than the extension, so a wrongly renamed file still reports its true type — exactly what you need to check the mapping in the table.

Output

package.json:   application/json
nuxt.config.ts: text/javascript

Guessing MIME types by extension in Python

python -c " import mimetypes for e in ['a.json', 'a.svg', 'a.wasm', 'a.csv', 'a.md']: print(e, '->', mimetypes.guess_type(e)[0]) "

guess_type consults the extension map only and never reads the file. For an extension missing from the table it returns None, and application/octet-stream is the fallback.

Output

a.json -> application/json
a.svg -> image/svg+xml
a.wasm -> application/wasm
a.csv -> text/csv
a.md -> text/markdown

Checking the Content-Type a live URL returns

curl -sI https://example.com | grep -i '^content-type'

When an API returns JSON but the browser offers to save the file, run this first to confirm the response header, then fix the mapping on the server or gateway.

Output

Content-Type: text/html; charset=utf-8

Serving three different types from one local server

node -e " const http = require('http'); const srv = http.createServer((q, s) => { if (q.url === '/sse') { s.writeHead(200, { 'Content-Type': 'text/event-stream' }); return s.end('data: hi\n\n'); } if (q.url === '/dl') { s.writeHead(200, { 'Content-Type': 'application/octet-stream' }); return s.end('x'); } s.writeHead(404, { 'Content-Type': 'text/plain' }); s.end('nope'); }); srv.listen(8931, async () => { for (const p of ['/x', '/sse', '/dl']) { const r = await fetch('http://127.0.0.1:8931' + p); console.log(p, r.status, r.headers.get('content-type')); } srv.close(); }); "

One server, three behaviours: octet-stream triggers a download, event-stream holds the connection open, text/plain renders inline. The only difference is the Content-Type header.

Output

/x 404 text/plain
/sse 200 text/event-stream
/dl 200 application/octet-stream

Common Pitfalls

  • The endpoint returns JSON yet the browser offers to save the file: check the response header first, the type is usually wrong or missing rather than the payload.
  • multipart/form-data requires a boundary parameter. Hand-writing the body without it makes the server report a missing boundary or parse no fields at all.
  • SVG is executable XML. Accepting .svg uploads without sanitizing hands attackers a script injection vector on your own pages.
  • Modern Office files need the vnd.openxmlformats-* names; sticking to the old msword / vnd.ms-excel types makes current Office report a mismatch between format and extension.
  • Declare font/woff2 first and keep woff or ttf as a fallback; offering only legacy formats makes modern browsers give up silently.

Tips

  • Nginx MIME types live in /etc/nginx/mime.types.
  • For file uploads set Content-Type to multipart/form-data; the browser handles boundaries.
  • JSON API responses should set Content-Type to application/json; charset=utf-8.
  • octet-stream triggers a browser download — use for unknown or forced-download types.

FAQ

text/javascript or application/javascript — which one?

Use text/javascript. application/javascript is a historical name that RFC 4329 re-registered as an obsolete alias of text/javascript; modern browsers, CDNs and minifiers handle the two differently and some refuse to execute the application form. The only remaining users are IE-era codebases, which are not worth accommodating.

Is application/json different from application/json; charset=utf-8?

Practically no, but writing the charset explicitly is still the better habit. JSON is UTF-8 by specification so the parameter is redundant, yet declaring it lets CDNs, browsers and debugging tools confirm the encoding at a glance instead of guessing a locale default. The charset actually matters for the text/* family, where legacy encoding ambiguity still exists.

Why is multipart/form-data always used for uploads?

Because it is not a single type but a framing format. The body is cut into segments by the boundary parameter, and each segment carries its own headers — text/plain for a plain field, a filename plus a type for a file. It exists only to carry binary data alongside ordinary fields. With no file in the payload, application/x-www-form-urlencoded is simpler and far easier for a server to parse.

SVG is an image — why is it image/svg+xml rather than a flat type like image/png?

Because SVG is not a bitmap but an XML document. The +xml suffix states that the payload is XML, and the image/ top-level type states what it is used for. The combination lets a browser render it as an image (inside <img> or as a CSS background) while keeping it parseable as XML for DOM access and script injection. The cost is that it holds two identities at once — script-capable and referenceable as an image — so uploads need stricter sanitizing than a PNG would.

When do I reach for application/octet-stream and application/x-www-form-urlencoded?

application/octet-stream is the "I do not know what this is" fallback; it makes the browser download the payload instead of trying to render it, so it suits arbitrary binary streams and is the safest default in the table. application/x-www-form-urlencoded is the default submission format for HTML forms, joining key-value pairs with & and percent-encoding the values. The deciding question is whether the body holds binary data: a file forces multipart, plain fields are simplest as urlencoded.

Official References

Each command links to its official documentation below, so you can verify the latest usage and read deeper.

Maintained by LaoHand

Publicly updated on Jul 21, 2026, continuously proofread against official docs.

Contact Us

Wrong command or description? Send us corrections, business inquiries or product feedback by email.

Contact Us