Content-Disposition: download prompts and file names
Content-Disposition tells the browser whether to display the body in the page or save it as a file, and what to call the file when it saves it.
At a glance
- Direction
- Response, and also inside each part of a multipart form upload.
- Defined in
- RFC 6266 for responses. Multipart form parts use RFC 7578.
- When absent
- The browser displays the body if it can render the media type, and otherwise offers to save it.
- Values
- inline to display in place, attachment to prompt a save
- filename
- ASCII only, and quoted if it contains spaces
- filename*
- Extended syntax for other characters, written as UTF-8''name with percent encoding
- In form uploads
- form-data with a name parameter, and filename for a file field
In detail
The disposition type is the important half. inline means render it here if you can, attachment means save it, and attachment applies even to media types the browser could display perfectly well. That is how a CSV becomes a download rather than a wall of text, and how a PDF opens in the file manager rather than in the built in viewer.
The plain filename parameter is limited to ASCII. For anything else, RFC 6266 defines filename* using the extended syntax from RFC 8187: the charset, two apostrophes for the empty language tag, and the percent encoded UTF-8 bytes. Sending both, plain first and extended second, gives every client something usable, and browsers that understand the extended form prefer it.
It is also a security control on user uploads. Serving user supplied files with attachment stops a file that happens to contain markup being rendered in your origin, which is the same class of problem X-Content-Type-Options addresses from the other direction. On a host serving arbitrary uploads, both are worth sending.
Inside a multipart form body the header appears again with a different job: it names the form field, and adds a filename parameter for file inputs. That usage is defined by the form data specification rather than by RFC 6266, which is why the syntax you see in an upload body does not match the syntax of a response header.
Examples
Content-Disposition: attachment; filename="report-2025.csv"Content-Disposition: attachment; filename="rapport.csv"; filename*=UTF-8''rapport%20annuel%20%C3%A9t%C3%A9.csvThe plain parameter is the fallback. Clients that understand the extended one use it and get the accented name.
Content-Disposition: form-data; name="avatar"; filename="me.png"
Content-Type: image/pngThings that catch people out
- Putting a path in the file name is dangerous on the receiving side. Strip directory separators from any name you take from an upload before touching the file system with it.
- A raw non-ASCII byte in the plain filename parameter is invalid and produces mangled names or a truncated header, depending on the client.
- A file name containing a quotation mark or a newline can break the header apart. Sanitise the value rather than interpolating it directly.
Try it: HTTP Headers Checker
Check a live URL or paste headers you already have. It grades six security headers from A+ to F and lists every other header the response returned.
HTTP Headers Checker
LOCAL · Browser-OnlyView HTTP response headers for any URL
Enter any website URL to fetch and analyze its HTTP response headers. We'll automatically add https:// if needed.
Why Check Security Headers?
Security headers protect your website against common attacks like XSS, clickjacking, and MIME sniffing. They're set by your web server and cost nothing to implement. Missing security headers are one of the most common findings in security audits.
Related HTTP headers
All http headers →Content-Type: media type, charset and boundary
How Content-Type is structured, why the charset parameter still matters, what boundary does on a multipart upload, and how a wrong type breaks a page.
X-Content-Type-Options: nosniff and MIME sniffing
What nosniff stops a browser doing, why it is the safest security header to add, and the two kinds of resource it starts rejecting once you turn it on.
Content-Length: the size of the body in octets
What Content-Length counts, why it must never accompany Transfer-Encoding, what happens when it disagrees with the body, and when it may be omitted.
Accept-Ranges: advertising support for partial requests
What Accept-Ranges advertises, why the value none is a deliberate statement, and how a missing header breaks resumable downloads and video seeking.
Content-Range: which bytes this partial response holds
How Content-Range describes a byte range, what the total size field means, the unsatisfied form sent with 416, and how multipart ranges are framed.
Range: asking for part of a resource
How to request a byte range, what a suffix range does, why a server may ignore the header and return 200, and how to resume a download safely.
Tools for this
- HTTP Request Builder Free online HTTP request builder - build and test HTTP requests with custom headers and body
- HTTP Headers Checker Free online HTTP headers checker - view HTTP response headers for any URL