Updated 9 hours ago
Every HTTP response carries a question the browser needs answered before it can do anything useful: "What am I looking at?"
The Content-Type header provides that answer. Without it, the same bytes that render as a photograph become meaningless garbage—or worse, executable code the browser didn't expect to run.
What Content-Type Actually Does
Content-Type specifies the media type (also called MIME type) of the data being transmitted. It appears in both requests and responses:
In responses, it tells the browser how to interpret what it received:
In requests, it tells the server how to parse what you're sending:
Get this wrong and things break silently. Send JSON with the wrong Content-Type and your server won't parse it. Serve an image with text/html and watch the browser try to render binary data as a webpage.
MIME Type Structure
MIME stands for "Multipurpose Internet Mail Extensions"—originally designed for email, adopted by HTTP. The format is simple:
The type is the broad category. The subtype is the specific format:
text/html— Text category, HTML formatimage/png— Image category, PNG formatapplication/json— Application category, JSON format
Some MIME types include parameters:
Common MIME Types
Text
| MIME Type | Use |
|---|---|
text/html | HTML webpages |
text/plain | Plain text without markup |
text/css | CSS stylesheets |
text/javascript | JavaScript code |
Application
| MIME Type | Use |
|---|---|
application/json | JSON data (the standard for modern APIs) |
application/xml | XML data |
application/pdf | PDF documents |
application/zip | ZIP archives |
application/octet-stream | Generic binary (when specific type is unknown) |
application/x-www-form-urlencoded | Form data encoded as URL parameters |
Images
| MIME Type | Use |
|---|---|
image/png | PNG images |
image/jpeg | JPEG images |
image/gif | GIF images |
image/svg+xml | SVG vector graphics |
image/webp | WebP (modern, efficient format) |
Video and Audio
| MIME Type | Use |
|---|---|
video/mp4 | MP4 videos |
video/webm | WebM videos |
audio/mpeg | MP3 audio |
audio/wav | WAV audio |
Multipart
multipart/form-data is special—it allows mixing different content types in a single request, essential for forms that include both text fields and file uploads:
Character Encoding
For text content, the charset parameter specifies how characters are encoded:
Always use UTF-8. It supports every character from every language, it's backward compatible with ASCII, and it's the universal standard. Other encodings like ISO-8859-1 or Shift_JIS exist for legacy compatibility, but unless you're maintaining ancient systems, UTF-8 is the answer.
Omitting the charset forces browsers to guess, and guessing leads to garbled text—the infamous "mojibake" where international characters become question marks or random symbols.
Content Negotiation
Clients can request specific formats using the Accept header:
The q parameter indicates preference (0 to 1). Here, JSON is most preferred (implicit q=1.0), XML is acceptable (q=0.9), and anything else is a last resort (q=0.8).
The server examines this and responds with the best match. This lets a single API endpoint serve JSON to web apps and XML to legacy systems, based on what each client asks for.
Why Getting This Wrong Is Dangerous
Security Vulnerabilities
Mislabeled content can turn your browser into an unwitting accomplice:
- Attacker uploads an HTML file containing malicious JavaScript
- Server stores it, perhaps as "profile-picture.jpg"
- Server serves it with
Content-Type: text/html - Browser obediently executes the JavaScript—XSS attack complete
The X-Content-Type-Options: nosniff header prevents browsers from second-guessing the Content-Type. With this header, the browser trusts your declaration absolutely—so you'd better get it right.
Silent API Failures
This is one of the most common debugging headaches:
The server sees the Content-Type, decides how to parse the body, and if they don't match, your data arrives as nonsense.
Broken Downloads and Displays
Browsers decide what to do based entirely on Content-Type:
text/html→ Parse and render as a webpageapplication/json→ Display raw text (or offer download)image/png→ Render inline as an imageapplication/pdf→ Open PDF viewerapplication/octet-stream→ Prompt to download
Serve a PDF with text/html and watch the browser try to render binary data as a webpage—a screen full of gibberish.
File Extensions Don't Matter (to HTTP)
File extensions like .jpg, .pdf, or .html are conventions for operating systems. HTTP doesn't care. The Content-Type header is the only truth.
A file named vacation.jpg served with Content-Type: application/pdf will open as a PDF. A file named malware.exe served with Content-Type: image/png will display as a (broken) image.
This creates a rule worth following: make extensions match Content-Type. Not because HTTP requires it, but because humans maintaining the system will thank you.
Custom MIME Types
Applications can define custom types, typically with the application/vnd. prefix (vendor-specific):
This GitHub API example encodes the vendor (GitHub), version (v3), and underlying format (JSON) all in one type. Useful for API versioning and proprietary formats.
Debugging Content-Type Issues
Browser DevTools make this visible:
- Open DevTools (F12)
- Go to the Network tab
- Click any request
- Check the Headers section
You'll see both the request's Content-Type (what you claimed to send) and the response's Content-Type (what the server claims it returned). When things break mysteriously, this is often where the answer hides.
Frequently Asked Questions About Content-Type and MIME Types
Was this page helpful?