Learning & reference

MIME types: the right Content-Type for every file

The Content-Type header decides whether a browser renders a file, downloads it, or refuses it outright. Here is the correct type for every common extension, and the mistakes that quietly break things.

What a MIME type actually controls

The Content-Type header decides whether the browser renders a file, downloads it, or refuses it. Get it wrong and a stylesheet is ignored, a script is blocked, or a PDF downloads instead of opening.

Render vs. download

application/octet-stream (or Content-Disposition: attachment) forces a download. A known type like application/pdf renders inline.

nosniff changes everything

With X-Content-Type-Options: nosniff the browser stops guessing. A stylesheet served as text/plain is then rejected outright rather than silently working.

It is client-supplied on upload

The Content-Type on a multipart upload comes from the browser and can be set to anything. Validate with a signature check, not this header.

Common types by extension

ExtensionMIME typeNotes
.txttext/plainAdd ; charset=utf-8 or browsers guess the encoding.
.html .htmtext/html
.csstext/cssServed as anything else, browsers refuse to apply it.
.js .mjstext/javascriptThe standard type. application/javascript is obsolete but still accepted.
.jsonapplication/jsonNo charset parameter - JSON is always UTF-8.
.xmlapplication/xmltext/xml is legacy and treats it as text.
.csvtext/csvExcel often mislabels these as application/vnd.ms-excel.
.pdfapplication/pdf
.pngimage/png
.jpg .jpegimage/jpegNote: not image/jpg - that type does not exist.
.gifimage/gif
.webpimage/webp
.svgimage/svg+xmlCan contain scripts - never serve user SVG from your main origin.
.icoimage/x-iconimage/vnd.microsoft.icon is the registered name.
.zipapplication/zip
.gzapplication/gzipNot Content-Encoding: gzip - that is a different thing.
.tarapplication/x-tar
.7zapplication/x-7z-compressed
.mp3audio/mpegNot audio/mp3.
.wavaudio/wav
.mp4video/mp4
.webmvideo/webm
.wofffont/woffModern types are font/*; older ones used application/font-woff.
.woff2font/woff2
.ttffont/ttf
.otffont/otf
.docxapplication/vnd.openxmlformats-officedocument.wordprocessingml.documentThe long OOXML types are a classic source of typos.
.xlsxapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet
.pptxapplication/vnd.openxmlformats-officedocument.presentationml.presentation
.docapplication/mswordLegacy binary Office.
.xlsapplication/vnd.ms-excel
.odtapplication/vnd.oasis.opendocument.text
.epubapplication/epub+zip
.wasmapplication/wasmMust be exact or streaming compilation fails.
(unknown)application/octet-streamThe safe default. Triggers a download rather than inline display.

The mistakes that bite

image/jpg

Does not exist. The registered type is image/jpeg; image/jpg is silently accepted by some stacks and rejected by others.

Missing charset

text/html without ; charset=utf-8 leaves the encoding to the browser - accented characters turn into mojibake.

gzip confusion

A .gz file is application/gzip content. Content-Encoding: gzip means "this response was compressed in transit" - set both and the client decompresses once too often.

SVG is executable

SVG can carry <script>. Serving user-uploaded SVG as image/svg+xml from your own origin is stored XSS.

CSV vs Excel

Excel labels CSV exports application/vnd.ms-excel. An importer that only accepts text/csv rejects a perfectly valid file.

OOXML typos

The Office types are ~70 characters long. One wrong character and the download is treated as an unknown binary.

See it live

The generator echoes any content type you ask for, so you can watch how a browser reacts.

Open the generator File signatures →

More from Learning

Guides and references for test data, file handling and AI evals. All free, no sign-up. See the full hub.

Synthetic data for AI evalsWhat you can download, what you buildRAG test corpusDocuments with extraction trapsJSONL for evalsThe format, and ten ways it breaksMock API for agentsRecords, pagination, failures on demandSafe test dataReserved domains, IPs, numbers & cardsSynthetic PIIFake people that reach nobodyTest card numbersEvery brand, declines, 3D SecureTest phone numbersReserved US, UK and Australian rangesReserved IP addressesDocumentation ranges and SSRF casesExample domains.test, .invalid, example.com, and trapsQA test stringsUnicode, emoji, injection & edge casesFilename compatibilityWhat breaks across Windows, Mac & LinuxFile systemsPOSIX, NTFS, APFS, ext4, SMB, NFS, NASFile signaturesMagic numbers that identify every formatCharacter encodingsUTF-8, UTF-16, BOM & normalizationUpload validationThe checklist, with a file for each checkHTTP status codesEvery code and when you actually see itDates & timesISO 8601, epoch, Excel serials, DSTHTTP headersContent-Type, Disposition, Range, CORSRegex cheat sheetSyntax, flags and ready-made patternsGenerate files (CLI)Make test files on any OSCrypto & certificatesSSL/PEM, hashing, encryptionWeb app testingWhat to test, with a file for each caseDesktop app testingPaths, names, encodings and savingMobile app testingPickers, photos, flaky networksCLI testingArguments, pipes and exit codesLarge file upload testingDefault limits, 413s and exact sizes1 GB test file1 GB and 2 GB, with SHA-25610 GB test fileMake one locally in secondsDownload speed test files10 MB to 2 GB of random data