Skip to content
ToolBoxGeniehome

MIME Type Lookup

Developer Tools · Added

The Content-Type header is the only thing that tells a browser what a file actually is — the extension is a hint to the operating system and nothing more. Get it wrong and the failures are baffling rather than obvious: a stylesheet that is silently ignored, a font that never loads, a WebAssembly module that refuses to compile. Search by extension or by type, and get the header to send along with whether it needs a charset, whether compressing it is worth anything, and what its file signature is.

Type an extension, a full MIME type, or a word from the description. A filename works too.

Filter by kind

45 of 45 types

Text and markup

ExtensionContent-TypeCharsetCompress
.html .htmtext/htmlHTML documentutf-8Yes
.csstext/cssCascading style sheetutf-8Yes
.js .mjstext/javascriptJavaScriptutf-8Yes
.txt .log .texttext/plainPlain textutf-8Yes
.csvtext/csvComma-separated valuesutf-8Yes
.md .markdowntext/markdownMarkdownutf-8Yes
.xmltext/xmlXMLutf-8Yes
.icstext/calendariCalendarutf-8Yes

Application and data

ExtensionContent-TypeCharsetCompress
.jsonapplication/jsonJSONYes
.jsonldapplication/ld+jsonJSON-LDYes
.pdfapplication/pdfPDFNo
.wasmapplication/wasmWebAssemblyYes
.bin .datapplication/octet-streamArbitrary binaryNo
application/x-www-form-urlencodedForm encodingYes
multipart/form-dataMultipart formNo
.docxapplication/vnd.openxmlformats-officedocument.wordprocessingml.documentWord documentNo
.xlsxapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetExcel spreadsheetNo
.rtfapplication/rtfRich textYes
.sqlapplication/sqlSQL scriptutf-8Yes

Images

ExtensionContent-TypeCharsetCompress
.jpg .jpeg .jpeimage/jpegJPEG imageNo
.pngimage/pngPNG imageNo
.gifimage/gifGIF imageNo
.webpimage/webpWebP imageNo
.avifimage/avifAVIF imageNo
.svgimage/svg+xmlSVG imageutf-8Yes
.icoimage/x-iconIconNo
.tif .tiffimage/tiffTIFF imageNo
.heicimage/heicHEIC imageNo

Audio

ExtensionContent-TypeCharsetCompress
.mp3audio/mpegMP3 audioNo
.wavaudio/wavWAV audioYes
.ogg .ogaaudio/oggOgg audioNo
.flacaudio/flacFLAC audioNo
.aac .m4aaudio/aacAAC audioNo

Video

ExtensionContent-TypeCharsetCompress
.mp4 .m4vvideo/mp4MP4 videoNo
.webmvideo/webmWebM videoNo
.movvideo/quicktimeQuickTime videoNo

Fonts

ExtensionContent-TypeCharsetCompress
.woff2font/woff2WOFF2 fontNo
.wofffont/woffWOFF fontNo
.ttffont/ttfTrueType fontYes
.otffont/otfOpenType fontYes

Archives

ExtensionContent-TypeCharsetCompress
.zipapplication/zipZIP archiveNo
.gzapplication/gzipGzip archiveNo
.tarapplication/x-tarTar archiveYes
.7zapplication/x-7z-compressed7-Zip archiveNo
.rarapplication/vnd.rarRAR archiveNo

The Content-Type header is the only thing that tells a browser what a file is — the extension is a hint to the operating system and nothing more. A stylesheet served as text/plain is ignored in standards mode, a WebAssembly module refuses to stream-compile under any type but application/wasm, and a font sent as octet-stream simply fails to load. When something mysteriously does not work, the header is the first thing to check.

How to use the mime type lookup

  1. 1Type an extension, a full MIME type, or a filename into the search box.
  2. 2An exact match appears at the top with the complete header to send.
  3. 3Check the charset row — text formats need one and binary formats must not have one.
  4. 4Check the compression row before configuring gzip or Brotli: already-compressed formats gain nothing.
  5. 5Use the file signature where you are validating uploads, since an extension can be renamed and the leading bytes cannot.

Examples

A stylesheet

Input
.css
Result
Content-Type: text/css; charset=utf-8

In standards mode a browser refuses a stylesheet sent as anything else, which produces an unstyled page and no obvious error.

JSON, and the charset trap

Input
application/json
Result
No charset parameter — JSON is defined as UTF-8

RFC 8259 fixes the encoding, so adding a charset is redundant and technically invalid.

A font

Input
.woff2
Result
font/woff2, and not worth compressing

WOFF2 is Brotli-compressed internally. Running gzip over it costs CPU to make the file very slightly larger.

About the mime type lookup

How a type gets decided, and where it goes wrong

For a static file, the web server looks up the extension in a table and sets the header. That table is usually `mime.types` for nginx or `mime.conf` for Apache, and it is where a missing entry causes trouble: an unrecognised extension falls back to application/octet-stream, which downloads rather than displays. Adding a new format to a site — a WOFF2 font, an AVIF image, a WebAssembly module — often means adding it to that table first.

For a dynamic response the application sets the header itself, and the common failure there is forgetting. A framework's default of text/html applied to a JSON API response will work in most clients and break the strict ones, and it defeats any content negotiation downstream.

The third source of trouble is a CDN or proxy that rewrites or drops the header. Anything that re-serves content has an opportunity to change what it claims to be, and a mismatch between what the origin sent and what arrives is worth checking whenever a file works locally and not in production.

Sniffing, and why it is switched off

Browsers historically guessed a file's type from its content when the header looked wrong, which was helpful in an era of badly configured servers and is a security problem now. If a user can upload a file that a site serves back, and the browser is willing to sniff it as HTML regardless of the declared type, then an uploaded file becomes a script running on the site's own origin.

The fix is the `X-Content-Type-Options: nosniff` header, which tells the browser to trust the declared type and refuse to guess. It is close to universal on well-configured sites now, and it raises the stakes on getting the type right: with sniffing disabled, a stylesheet sent as text/plain is not quietly rescued, it is simply not applied.

The practical consequence is that the Content-Type header has gone from a hint to a contract. It is worth checking with `curl -I` when something behaves oddly, because a wrong type produces symptoms that look like almost anything else — a caching problem, a build failure, a broken file — and almost never looks like what it is.

Frequently asked questions

Is the extension or the Content-Type authoritative?
The header, always, for anything served over HTTP. A browser decides what to do with a response based on the type it was told, not on what the URL ends in — so `styles.css` served as text/plain is not a stylesheet, and `image.txt` served as image/png renders as an image. Extensions matter to the operating system when a file is saved to disk, and to the server when it is deciding which type to send, but the header is what actually governs.
When should I add charset=utf-8?
On text formats, where the bytes are characters and something has to say which encoding those characters are in — HTML, CSS, JavaScript, plain text, CSV, SVG. Not on binary formats, where a charset is meaningless. And not on JSON, which is an exception worth knowing: its specification fixes the encoding as UTF-8, so the parameter is redundant and some tooling treats its presence as a misconfiguration.
Why should I not compress images and video?
Because they are already compressed, thoroughly, by algorithms designed for their specific content. Running gzip over a JPEG typically makes it a fraction of a percent larger while consuming CPU at both ends. The formats worth compressing are the text ones — HTML, CSS, JavaScript, JSON, SVG — which routinely shrink by 60 to 80 percent. The one surprise on the list is WAV, which is genuinely uncompressed audio and does benefit.
What are magic bytes and why would I check them?
They are a signature at the start of a file that identifies its format: JPEG starts FF D8 FF, PNG starts with 89 followed by "PNG", and any ZIP-based format including DOCX and XLSX starts with "PK". They matter for upload validation, because an extension and a client-supplied Content-Type are both trivially forged. Checking the actual leading bytes is what tells you whether a file claiming to be an image is one.
Why do some types have more than one name?
Usually because the registered type changed while the old one stayed in use. JavaScript is the clearest case: it was text/javascript, then application/javascript was preferred for years, and the HTML specification has now made text/javascript the correct one again. Browsers accept several spellings for compatibility, but a server should send the current registered type, which is what this page lists first with the alternatives noted alongside.