MIME Type Lookup

The MIME type for any file extension, and the extension for any type. Search either way. The types that servers most often get wrong carry a note explaining the mistake.

Text and web

.html .htm
text/html
HTML document
.css
text/css
Stylesheet
.js .mjs
text/javascript
JavaScript application/javascript was deprecated in favor of text/javascript. Plenty of servers and tutorials still send the old name.
.json
application/json
JSON
.jsonld
application/ld+json
JSON-LD Structured data blocks need this exact type or Google ignores them.
.xml
application/xml
XML text/xml is also valid but signals the payload is human-readable, which it rarely is.
.csv
text/csv
CSV
.txt
text/plain
Plain text
.md .markdown
text/markdown
Markdown
.ics
text/calendar
iCalendar
.vcf
text/vcard
vCard contact
.wasm
application/wasm
WebAssembly Must be exact: streaming compilation refuses anything else.

Images

.png
image/png
PNG
.jpg .jpeg
image/jpeg
JPEG image/jpg is not a real type, despite the extension.
.webp
image/webp
WebP
.avif
image/avif
AVIF
.gif
image/gif
GIF
.svg
image/svg+xml
SVG Serving it as text/xml or text/plain stops the browser rendering it.
.ico
image/x-icon
Icon image/vnd.microsoft.icon is the registered name; the x- form is what everyone sends.
.bmp
image/bmp
Bitmap
.tif .tiff
image/tiff
TIFF
.heic
image/heic
HEIC What an iPhone shoots by default. No browser renders it.

Fonts

.woff2
font/woff2
WOFF2 The whole family moved from application/x-font-* to font/* in RFC 8081. Old values still turn up in stale configs.
.woff
font/woff
WOFF
.ttf
font/ttf
TrueType
.otf
font/otf
OpenType
.eot
application/vnd.ms-fontobject
Embedded OpenType IE only, and IE is gone. Safe to drop.

Audio and video

.mp4 .m4v
video/mp4
MP4 video
.webm
video/webm
WebM video
.mov
video/quicktime
QuickTime
.mp3
audio/mpeg
MP3 audio/mp3 is not registered; the correct type is audio/mpeg.
.m4a
audio/mp4
M4A audio
.wav
audio/wav
WAV
.ogg .oga
audio/ogg
Ogg audio
.flac
audio/flac
FLAC
.vtt
text/vtt
WebVTT subtitles

Documents

.pdf
application/pdf
PDF
.doc
application/msword
Word (legacy)
.docx
application/vnd.openxmlformats-officedocument.wordprocessingml.document
Word
.xls
application/vnd.ms-excel
Excel (legacy)
.xlsx
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Excel
.ppt
application/vnd.ms-powerpoint
PowerPoint (legacy)
.pptx
application/vnd.openxmlformats-officedocument.presentationml.presentation
PowerPoint
.odt
application/vnd.oasis.opendocument.text
OpenDocument text
.ods
application/vnd.oasis.opendocument.spreadsheet
OpenDocument sheet
.rtf
application/rtf
Rich Text
.epub
application/epub+zip
EPUB

Archives and binaries

.zip
application/zip
ZIP archive
.gz
application/gzip
gzip
.tar
application/x-tar
tar archive
.7z
application/x-7z-compressed
7-Zip
.rar
application/vnd.rar
RAR
.bz2
application/x-bzip2
bzip2
.bin .exe .dmg
application/octet-stream
Arbitrary bytes The fallback when nothing is known. Browsers download rather than render it, which is why a font served this way fails.

Form and API payloads

no extension
application/x-www-form-urlencoded
Standard form post The x- prefix was deprecated in 2012 but this one is far too widespread to rename.
no extension
multipart/form-data
Form with file upload
no extension
application/problem+json
API error body RFC 9457. A standard shape for API error responses. Worth adopting if your errors are ad hoc JSON today.
no extension
text/event-stream
Server-Sent Events
no extension
application/graphql-response+json
GraphQL response

1 Why a wrong type breaks things

The browser trusts the Content-Type header, not the extension. It decides what to do with a response from that header, and ignores the file extension in the URL. Serve a font as application/octet-stream and it refuses to use it. Serve an SVG as text/plain and you get the source code on screen instead of a picture. Serve a module with a non-JavaScript type such as text/plain and strict MIME checking blocks it.

When something will not load, read the response headers before you change any code. A wrong Content-Type is a more common cause than broken markup.

2 Never trust the type on an upload

The Content-Type on an uploaded file is set by the client and can say anything. A PHP script renamed to .jpg and declared as image/jpeg is a classic upload bypass, and checking the extension is no better.

Check the magic bytes at the start of the file on the server: finfo_file in PHP, python-magic in Python, file-type in Node. Then serve user uploads from a separate domain with X-Content-Type-Options: nosniff, so a browser cannot sniff them into a different, executable type.

3 Four details that cause wrong types

charset matters for text

text/html without charset=utf-8 makes the browser guess, and a guess of Latin-1 on UTF-8 content turns accented characters into mojibake (é shows as é).

The x- prefix is deprecated

RFC 6648 deprecated it in 2012. Some survivors are too entrenched to rename, application/x-www-form-urlencoded above all.

Fonts moved namespace

RFC 8081 gave fonts their own font/* tree. Old configs still say application/x-font-woff, which mostly works and is no longer correct.

octet-stream means download

Use it when the server does not know the type. For anything the browser should render, it makes the browser download the file instead.

How to use the MIME Type Lookup tool

  1. Type an extension, with or without the leading dot, to find its type.
  2. Type a type such as image/ or font to see everything in that family.
  3. Search by name too: spreadsheet, subtitle, archive.
  4. Types that servers often get wrong carry a note explaining the mistake.

Setting and checking Content-Type

nginx

# Types come from mime.types; add the ones it misses
types {
    application/wasm  wasm;
    image/avif        avif;
}

# charset matters for text, or the browser guesses
charset utf-8;
charset_types text/css text/plain application/javascript application/json;

# Stop the browser second-guessing you, and stop it
# interpreting a user upload as something executable
add_header X-Content-Type-Options "nosniff" always;

Detecting a real type on upload

<?php
// NEVER trust $_FILES['x']['type']: it comes from the client
$declared = $_FILES['avatar']['type'];        // attacker-controlled

// Read the magic bytes instead
$finfo = new finfo(FILEINFO_MIME_TYPE);
$actual = $finfo->file($_FILES['avatar']['tmp_name']);

$allowed = ['image/jpeg', 'image/png', 'image/webp'];
if (!in_array($actual, $allowed, true)) {
    http_response_code(415);
    exit('Unsupported file type');
}

// Then store it with an extension you chose, not one they sent,
// and serve it from a domain that cannot run scripts.

Checking the extension is no better than checking the declared type. Both are supplied by whoever is uploading.

Python

import mimetypes

print(mimetypes.guess_type("report.xlsx")[0])
print(mimetypes.guess_extension("image/webp"))

# The stdlib table is incomplete and platform-dependent.
# For real detection, read the bytes:
# pip install python-magic
import magic
print(magic.from_buffer(open("unknown.bin", "rb").read(2048), mime=True))

Common errors and how to fix them

A web font will not load
It is most likely being served as application/octet-stream, and browsers refuse a font with the wrong type. Add font/woff2 to your server's type table.
A module script is blocked
Strict MIME checking rejects anything but a JavaScript type. Serve it as text/javascript; application/javascript is deprecated but still accepted.
An SVG shows as source code
Served as text/plain or text/xml. It needs image/svg+xml to render.
Accented characters render as mojibake
No charset on a text type, so the browser guessed a different encoding. Add charset=utf-8.
An uploaded file executed on the server
The type was trusted. Check magic bytes, rename with your own extension, store outside the web root or on a separate domain, and send nosniff.

Good to know

MIME stands for Multipurpose Internet Mail Extensions: the scheme was designed in 1992 for email attachments and only later borrowed by HTTP. That is why IANA maintains the registry rather than a web standards body, and why some names, such as message/rfc822, come from email.

Specifications and references

This tool follows the specifications below. Read them when you need the exact normative wording, for example to settle an edge case between two implementations.

Frequently Asked Questions

Why does my font or video not load?

Usually the server is sending the wrong Content-Type, or none. Browsers refuse a font served as application/octet-stream, and a video can fail to play with the wrong type. Check the response headers before you change anything else.

What is the correct type for a JavaScript module?

text/javascript. The WHATWG and RFC 9239 deprecated application/javascript in favor of it, the reverse of what many developers expect. Both work in browsers; only text/javascript is current.

Should I trust the type a browser sends on upload?

No. The Content-Type on an uploaded file comes from the client and can say anything. Check the magic bytes at the start of the file on the server, and never decide what to do with a file based on its extension or its claimed type.

What does charset=utf-8 do?

It tells the browser how to decode the bytes of a text type. Without it, the browser guesses, and a guess of Latin-1 on UTF-8 content renders accented characters as mojibake (é becomes é).

Why do some types start with x-?

The x- prefix once marked unregistered experimental types. RFC 6648 deprecated the convention in 2012, but plenty survive, like application/x-www-form-urlencoded, which is far too widely used to rename now.

Related

For the rest of the response, the HTTP status code reference covers the status line. Data URIs carry their MIME type inline, which the image to Base64 tool builds for you.

More Developer Reference

Browse all developer reference

Copied to clipboard!