MIME Types Lookup_
Type an extension, a filename or a MIME type and get the other half, with the exact Content-Type header to send — including whether it takes a charset, because several common ones must not.
The header is a claim, not a fact. Browsers second-guess it by reading the first bytes, servers get several of these wrong by default, and on an upload path the type is supplied by whoever is uploading. That is usually what people are really trying to fix.
Showing the 58 types the web actually serves, not the whole IANA registry — see the specs below for what that leaves out.
- Input
- An extension, a filename, a full MIME type, or the name of a format.
- Output
- The type to send, the extensions it covers, the Content-Type header with a charset where one belongs, and anything worth knowing before you send it.
- Processing
- A curated set held in the page. Nothing is fetched and there is no registry lookup at request time.
- Limits
- Not a mirror of the IANA registry, which holds thousands of entries almost none of which are ever served over HTTP. This covers the web set plus the formats people demonstrably look up.
- The header is a claim
- A browser may sniff the first bytes and override you; X-Content-Type-Options: nosniff stops that. On an upload, the type comes from the client and cannot be trusted at all.
The Content-Type header is a claim, not a fact
Browsers second-guess you, and always have
A browser that receives a file reads the first few bytes and forms its own opinion. Historically that opinion could beat the header, which is how a file served as text/plain could be treated as HTML and run script from a domain that never intended to host any. X-Content-Type-Options: nosniff turns the guessing off, and once it is on, the type has to be right: a stylesheet sent as text/plain is dropped, and a script sent as anything that is not a JavaScript type refuses to execute. That refusal is one of the commonest console errors on the web.
On an upload, the type comes from the attacker
In a multipart/form-data request the client states the type of each part. It is a field in the request body, set by whatever is doing the uploading, so a file claiming to be image/png tells you only what the uploader wanted you to believe. Validate by reading the bytes, store uploads with a type you chose rather than one you were given, and serve anything user-supplied as application/octet-stream unless you have a reason not to. SVG deserves particular care: it is a document, it can contain script, and serving user SVG from your own origin is a stored-XSS vector.
Several common types are simply wrong
image/jpg has never existed — the extension is jpg, the type is image/jpeg. audio/mp3 was never registered either. JavaScript moved to text/javascript in 2022 and the application/* spellings are formally obsolete, though most tables still list them. Fonts moved to their own font/* top level in 2017. Each of these works most of the time, which is exactly why they persist: nothing fails until something strict is in the path.
Charset belongs on some of these and not others
Text formats take a charset and should be given one, because the fallback is a guess. Binary formats must not have one. The trap is application/json, which is textual and still takes no charset parameter — the format fixes UTF-8 itself and registers no such parameter, so sending one is undefined rather than merely redundant. The header shown for each entry here already applies that rule, so copying it is safe.
Look it up, copy the header
- 01Type an extension, a whole filename, or a MIME type. It searches both directions at once, so "docx" and "application/pdf" both work.
- 02Read the Content-Type row — that is the header to send, with a charset already included or deliberately absent.
- 03Check the note. Several formats carry a real caveat: SVG can execute, HEIC does not display, WebAssembly needs the exact type to stream.
- 04If a browser is refusing a file rather than mislabelling it, the troubleshooting table below covers the errors people actually hit.
Four things that go wrong with a Content-Type
A script that refuses to run
The console says strict MIME type checking is enabled.
text/html — your 404 page
text/javascript
A CSV that opens instead of downloading
Excel exported it and claimed its own type.
application/vnd.ms-excel
text/csv
An uploaded avatar that runs script
An SVG accepted because the client said image/svg+xml.
image/svg+xml
application/octet-stream, off-origin
WebAssembly that will not stream
instantiateStreaming fails on a file that is perfectly valid.
application/octet-stream
application/wasm
Types that are wrong but widespread
| What gets sent | What it should be | Why |
|---|---|---|
image/jpg | image/jpeg | The extension is jpg; the type has never been. Browsers tolerate it, strict parsers do not. |
audio/mp3 | audio/mpeg | Never registered. MP3 audio is an MPEG stream and the type reflects that. |
application/javascript | text/javascript | RFC 9239 marked the application/* and text/ecmascript forms obsolete in 2022. |
application/json; charset=utf-8 | application/json | JSON has no charset parameter. RFC 8259 fixes the encoding as UTF-8, so the parameter is undefined rather than merely redundant. |
application/x-zip-compressed | application/zip | A legacy Windows spelling that still arrives on uploads from Explorer. |
application/font-woff2 | font/woff2 | RFC 8081 moved fonts to their own top-level type in 2017. |
text/xml with no charset | application/xml | text/xml defaults to US-ASCII when the charset is omitted, so non-ASCII content breaks. |
application/vnd.ms-excel for a .csv | text/csv | What Excel claims when it exports. It makes browsers open the file in a spreadsheet rather than treat it as text. |
Every one of these is emitted by a real server or library. They work until something strict is in the path — a nosniff header, a CDN, a stricter runtime — and then they stop working all at once.
When the browser refuses the file
| Message | What it means | What to do |
|---|---|---|
Removed attachment of banned MIME type | A mail server or messaging gateway stripped a file because its type is on a blocklist — most often an executable, a script, or an archive that could contain one. On Android this usually comes from the carrier’s MMS gateway rather than from the phone. | Rename is not enough, because the filter reads the bytes as well as the name. Put the file in a password-protected archive, or send a link instead of the file. |
No video with supported format and MIME type found | Firefox is saying one of two different things. Either the server sent a type it cannot play, or the type is right and the CODECS inside the container are not supported — an MP4 holding H.265 is the usual case, since the container is fine and the video stream is not. | Check the response header first: a video served as application/octet-stream will fail even when the file is perfect. If the type is correct, re-encode to H.264 or offer a WebM alternative. |
Refused to execute script — strict MIME type checking is enabled | The page sent X-Content-Type-Options: nosniff and the script arrived with a type that is not a JavaScript type. The commonest cause is a 404 page: the server returned HTML where a .js file was expected, and the browser refused to run HTML as script. | Open the failing URL directly. If you get your site’s 404 page, the path is wrong. If you get the script, fix the server so it sends text/javascript. |
Resource interpreted as Stylesheet but transferred with MIME type text/plain | The server does not recognise .css and fell back to text/plain. Without nosniff the browser may still apply it; with nosniff it will not. | Add the mapping to the server config. In nginx that is the mime.types file; in Apache, AddType text/css .css. |
These are the MIME questions people search for most, and none of them is answered by a table of extensions — so they are answered here instead.
Getting Content-Type right
- Send
X-Content-Type-Options: nosniffand then make the types correct. Turning off sniffing is the security win; the correctness it forces is the cost, and it is worth paying. - Never trust the type on an upload. It is a field in the request that the uploader filled in — validate by reading the file, and store the type you determined rather than the one you were handed.
- Serve user-uploaded files from a different origin, or as
application/octet-streamwithContent-Disposition: attachment. That neutralises the whole class of problem rather than one file format at a time. - Add a charset to text formats and to nothing else — with the single exception of JSON, which is text and still takes none.
- When a file downloads instead of displaying, or displays instead of downloading, the lever is usually
Content-Dispositionrather than the type. - Check what your server actually sends rather than what its config says:
curl -Iagainst the URL settles it in one line.
Where MIME types mislead
An extension is not evidence of anything
Renaming a file changes nothing about its contents, and a filter that trusts the extension is trivially bypassed. Equally, a correct extension does not guarantee the type — the mapping here tells you what to SEND for a given format, not what an arbitrary file actually is.
SVG is a document, not a picture
It is XML, it can contain script and external references, and browsers execute it when it is served as image/svg+xml from your origin. Uploaded SVG is one of the most reliable stored-XSS vectors there is. Sanitise it, or serve it from a domain that has nothing to lose.
The container is not the codecs
A file can be a perfectly valid MP4 and still refuse to play, because the video stream inside uses a codec the browser does not support. "No video with supported format and MIME type found" says both possibilities at once, which is why it is so often misdiagnosed as a header problem when the header is fine.
This is not the full IANA registry
The registry holds thousands of media types, the overwhelming majority of which are never served over HTTP. This set covers the web formats plus the ones people look up, and stops there. For an obscure vendor type, the registry itself is the source of truth.
Some formats have two types and both are used
XML is served as both application/xml and text/xml, and the difference is real: text/xml assumes US-ASCII when the charset is omitted. Icons are registered as image/vnd.microsoft.icon and sent as image/x-icon by nearly everyone. The entry names the alternative rather than pretending there is one answer.
What this set covers, and how it decides
- Coverage
- 58 types spanning text, application, image, audio, video, font and archive formats — the web set plus the formats with measurable lookup demand. Deliberately not a registry mirror
- Lookup
- One field, both directions. An exact type match ranks first, then a filename or bare extension, then anything containing the query, so a partial like "openxmlformats" finds the whole Office family
- Charset rule
- Added to textual formats and omitted from binary ones, with
application/jsonandapplication/ld+jsonexcluded explicitly because JSON registers no charset parameter at all - Registration
- Each entry records whether the type is registered with IANA or merely conventional. image/x-icon, application/x-tar and video/webm are in the second group and are still what everyone sends
- Ambiguity
- Where a format has competing types in the wild, the correct one is the answer and the alternative is named in the note rather than silently dropped
- Obsolete forms
- application/javascript, audio/mp3, image/jpg and application/font-woff2 are absent from the data by design and appear only in the mistakes table, so a lookup can never return one
- Related
- Response headers more broadly are on HTTP status codes; encoding a file for a data URL is Base64 encode
- Network
- None from tool code. A test sweep calls every function this page uses with
fetchandXMLHttpRequestreplaced by stubs that throw, so a stray request fails the build instead of shipping. Disconnect from the network and the page still works.
Questions about MIME types
What is the MIME type for a PDF?
application/pdf. Send it as-is with no charset, since it is binary. If you want the browser to download it rather than open it in the built-in viewer, that is Content-Disposition: attachment — the type stays the same either way.
What is the MIME type for a .docx or .xlsx file?
They are the long ones: application/vnd.openxmlformats-officedocument.wordprocessingml.document for .docx and ...spreadsheetml.sheet for .xlsx. The older .doc and .xls are application/msword and application/vnd.ms-excel. Search either extension above to copy the full string rather than typing it.
Is it application/javascript or text/javascript?
text/javascript. RFC 9239 made it the standard in 2022 and marked application/javascript, application/x-javascript and text/ecmascript obsolete. All of them still work in browsers, which is why most tables have not caught up, but new configuration should use text/javascript.
Should application/json have charset=utf-8?
No. JSON registers no charset parameter — RFC 8259 fixes the encoding as UTF-8 — so the parameter is undefined rather than merely redundant. Implementations ignore it in practice and nothing breaks, but it should not be sent, and the header this page gives you omits it.
Why does my script fail with "strict MIME type checking is enabled"?
The page sends X-Content-Type-Options: nosniff and the script arrived with a type that is not a JavaScript type. Nine times out of ten the server returned an HTML 404 page for a path that does not exist, and the browser refused to run HTML as script. Open the URL directly — if you see your 404 page, the path is wrong, not the type.
Can I trust the MIME type on an uploaded file?
No. In a multipart form the client states the type of each part, so it is entirely attacker-controlled. Determine the type by reading the file, store the one you determined, and serve user content as application/octet-stream or from a separate origin. SVG is the format to be most careful with, because it can contain script.
What does "removed attachment of banned MIME type" mean?
A mail server or messaging gateway stripped the file because its type is blocklisted — usually an executable, a script, or an archive that might contain one. On Android it typically comes from the carrier gateway rather than the phone. Renaming does not help, since the filter reads the bytes too; send a link, or put it in a password-protected archive.
Is anything I type here sent anywhere?
The work is JavaScript running in this tab. Every function it calls is covered by a test that stubs fetch and XMLHttpRequest to throw, so a request that slipped in would break the build rather than reach a server — and you can confirm it for yourself by disconnecting and carrying on.