Content-Disposition Filename Pitfalls Across Browsers
Level: intermediate · ~11 min read · Intent: informational
Audience: developers, ops engineers, backend engineers, data analysts
Prerequisites
- basic familiarity with HTTP response headers
- optional: familiarity with file downloads in browsers
Key takeaways
- Content-Disposition filename handling is not fully uniform across browsers, especially around UTF-8 names, percent escapes, and fallback behavior.
- The safest practical pattern is usually to send both filename and filename*, with an ASCII-friendly fallback and a UTF-8 filename* value.
- Download behavior depends on more than one header: Content-Disposition, Content-Type, same-origin rules, the HTML download attribute, and browser-specific heuristics all play a role.
FAQ
- What is the difference between filename and filename* in Content-Disposition?
- filename is the older parameter and is best treated as an ASCII-oriented fallback, while filename* uses RFC 5987 style encoding and is the better option for UTF-8 filenames.
- Should I send both filename and filename*?
- Usually yes. That is the safest way to support modern browsers while still providing a fallback for older or less consistent implementations.
- Why do filenames behave differently across browsers?
- Browsers differ in how they handle percent escapes, UTF-8, same-origin download behavior, and the interaction between Content-Disposition and the HTML download attribute.
- Can the browser still change my suggested filename?
- Yes. Browsers may modify filenames to fit filesystem rules, replace path separators, or apply their own download behavior and safety rules.
Content-Disposition Filename Pitfalls Across Browsers
Content-Disposition looks simple until you try to make filenames behave consistently across browsers.
At a glance, the job seems easy: set Content-Disposition: attachment, add a filename, and let the browser do the rest. In practice, filename behavior gets messy quickly once you involve:
- spaces
- UTF-8 characters
- percent escapes
filenameversusfilename*- the HTML
downloadattribute - same-origin versus cross-origin downloads
- browser-specific cleanup rules for illegal path characters
This matters even more for CSV exports, where filenames often include dates, report names, locale-specific words, and customer-facing labels. If the filename breaks, the download still works, but the experience becomes sloppy and support teams start seeing tickets like:
- "The file downloaded with the wrong name"
- "Safari kept the percent signs"
- "The filename lost accented characters"
- "The browser ignored the name in my link"
- "The CSV saved as something unexpected"
This guide explains the practical filename pitfalls, why they happen, and the safest patterns to use.
If you want the practical tools first, start with the CSV Validator, CSV Format Checker, CSV Delimiter Checker, CSV Header Checker, CSV Row Checker, or the universal converter.
What Content-Disposition actually does
In HTTP responses, Content-Disposition tells the browser whether a payload should be treated as inline content or as a downloadable attachment, and it can also suggest a filename.
Typical examples look like this:
Content-Disposition: attachment
or:
Content-Disposition: attachment; filename="report.csv"
That sounds straightforward, but filename behavior is only partly defined by this one header. The browser also considers:
- whether
filenameorfilename*is present - whether the resource is same-origin
- whether an
<a download>attribute is involved - filesystem restrictions on the local machine
- whether the name contains percent escapes or non-ASCII characters
That is why two downloads with "the same filename" can behave differently across browsers.
Why filename and filename* both exist
This is the first thing that confuses many teams.
filename
filename is the older parameter. It is the more traditional form, and for practical interoperability it is safest when used as a simple ASCII-friendly fallback.
Example:
Content-Disposition: attachment; filename="report.csv"
filename*
filename* is the internationalized form. It uses the encoding defined in RFC 5987 and is the better choice for UTF-8 filenames.
Example:
Content-Disposition: attachment; filename*=UTF-8''r%C3%A9sum%C3%A9.csv
MDN explicitly says that when both are present, filename* is preferred over filename when both are understood. MDN also recommends sending both for maximum compatibility. That is the most important practical rule to remember. (MDN Content-Disposition)
The safest practical pattern
For modern web downloads, the safest common pattern is usually:
Content-Disposition: attachment; filename="report.csv"; filename*=UTF-8''report.csv
And for a UTF-8 name with non-ASCII characters:
Content-Disposition: attachment; filename="resume.csv"; filename*=UTF-8''r%C3%A9sum%C3%A9.csv
That gives you:
- a simpler fallback name for older or less consistent clients
- a standards-based UTF-8 name for clients that support
filename*
RFC 6266 Appendix D goes further and gives practical generation advice:
- include
filenamewhen ASCII is expressive enough - use quoted-string form when the filename has spaces or other disallowed token characters
- include
filename*when the desired name cannot be expressed faithfully infilename - include a fallback
filenameas well when possible - use UTF-8 for
filename*(RFC 6266 Appendix D)
That advice still maps well to real-world browser behavior.
Why percent escapes are a trap
One of the easiest filename mistakes is assuming that percent escapes behave consistently in the plain filename parameter.
They do not.
MDN explicitly warns that you may want to avoid percent escape sequences in filename because browsers handle them inconsistently: Firefox and Chrome decode them, while Safari does not. (MDN Content-Disposition)
That means a header like this can produce different user-visible filenames:
Content-Disposition: attachment; filename="report%20march.csv"
In some browsers, the user may effectively see report march.csv. In others, the literal %20 may remain in the filename.
This is one of the strongest reasons to keep plain filename simple and ASCII-friendly, and to put real UTF-8 intent into filename*.
Why quoted filenames still matter
Another common mistake is leaving quotes off when the filename contains spaces or other special characters.
Example:
Content-Disposition: attachment; filename=report march.csv
That is much more fragile than:
Content-Disposition: attachment; filename="report march.csv"
MDN notes that quotes around the filename are optional in some cases, but necessary when you use special characters like spaces. RFC 6266 Appendix D also advises using the token form only when the filename does not contain disallowed characters and using quoted-string otherwise. (MDN Content-Disposition) (RFC 6266 Appendix D)
So the practical rule is simple:
If the fallback filename contains spaces, quote it.
Non-ASCII characters: where teams get burned
This is the other big browser-facing pitfall.
If you put non-ASCII characters directly into the plain filename parameter, behavior becomes less predictable. RFC 6266 specifically advises avoiding non-ASCII characters in filename and using filename* when you need to express the name faithfully. (RFC 6266 Appendix D)
That is why a safer pair looks like:
Content-Disposition: attachment; filename="resume.csv"; filename*=UTF-8''r%C3%A9sum%C3%A9.csv
instead of trying to rely on:
Content-Disposition: attachment; filename="résumé.csv"
The second form may appear to work in many cases, but it is a less disciplined interoperability pattern.
Browsers can still rewrite the suggested name
Even if you send a clean header, the browser may still transform the suggested filename.
MDN notes that browsers may apply transformations to conform to filesystem requirements, including converting path separators / and \ to underscores. The HTML <a> docs also note that / and \ in the download attribute filename are converted to underscores and that filesystems may forbid other characters too, so browsers may adjust the suggested name. (MDN Content-Disposition) (MDN element)
This means:
- do not rely on path-like segments in filenames
- do not assume the exact string will survive unchanged
- treat the filename as a suggestion, not an unchangeable result
The download attribute changes the picture
Teams sometimes assume the response header is the whole story. It is not.
The HTML <a download> attribute can also suggest a filename and influence whether a resource is treated as a download.
MDN’s <a> docs make a few important points:
downloadonly works for same-origin URLs, orblob:anddata:URLs- if
Content-Dispositionspecifies a filename, that filename takes priority over the filename in thedownloadattribute - if
Content-Dispositionsaysinline, Chrome and Firefox prioritize the attribute and still treat it as a download for same-origin URLs - older Firefox behavior differed before version 82 (MDN element)
This creates several real-world pitfalls:
Pitfall 1: assuming download="x.csv" will override the server header
If the response header provides a filename, MDN says the header wins over the attribute’s filename suggestion.
Pitfall 2: expecting download to work the same cross-origin
It does not. Same-origin restrictions matter.
Pitfall 3: mixing inline with download and expecting universal consistency
Modern Chrome and Firefox prioritize the attribute in same-origin cases, but older behavior differed.
CSV downloads make these issues more visible
This topic matters for all file downloads, but CSV exports have some especially common filename patterns that trigger bugs:
- report names with spaces
- dates in the filename
- localized names with accents or non-English text
- generated names with user or company labels
- characters copied from report titles
- attempts to include slashes like
2026/04/report.csv
CSV exports also commonly come from:
- admin dashboards
- signed URLs
- API endpoints
- background report jobs
- browser links with
downloadattributes - same-origin and cross-origin file delivery mixes
That combination makes filename mistakes more visible than teams expect.
A safer filename recipe for CSV exports
For most CSV download endpoints, a disciplined filename pattern looks like this:
- Choose a filesystem-safe ASCII fallback for
filename - Quote it when it contains spaces
- Add a UTF-8
filename*when you want to preserve international characters - Avoid percent escapes in plain
filename - Avoid slashes and backslashes
- Keep the extension clear and correct
Example:
Content-Disposition: attachment; filename="sales-report-april-2026.csv"; filename*=UTF-8''sales-r%C3%A9sum%C3%A9-avril-2026.csv
In many cases, the fallback can simply be a normalized ASCII version of the prettier UTF-8 name.
Common mistakes to avoid
1. Sending only a UTF-8-looking filename and skipping filename*
This often works until it does not.
2. Putting percent escapes into plain filename
Safari is the classic place where this looks wrong, while Chrome and Firefox may decode it.
3. Leaving spaces unquoted
This is avoidable and brittle.
4. Assuming the browser will keep slashes or path-like segments
Browsers may normalize these into underscores.
5. Expecting the download attribute to always win
It does not. Header-provided filenames take precedence over the attribute’s filename suggestion.
6. Forgetting same-origin rules around download
A link that behaves correctly on a same-origin export endpoint may behave differently on a CDN or signed URL.
A practical decision framework
Use this when implementing download filenames.
Use only filename when:
- the name is simple ASCII
- there are no non-ASCII characters to preserve
- you want maximum simplicity
Example:
Content-Disposition: attachment; filename="report.csv"
Use both filename and filename* when:
- the real filename contains non-ASCII characters
- you want better modern browser fidelity
- you still want a broad fallback strategy
Example:
Content-Disposition: attachment; filename="resume.csv"; filename*=UTF-8''r%C3%A9sum%C3%A9.csv
Use a conservative ASCII fallback when:
- support tickets from older or inconsistent clients matter
- downstream automation expects simpler names
- you want predictable fallback behavior
Avoid cleverness when:
- the value contains spaces, punctuation, or Unicode you have not tested
- you are tempted to percent-encode everything into
filename - you are mixing
downloadattribute assumptions with server header assumptions
Example header patterns
Simple safe ASCII CSV
Content-Disposition: attachment; filename="customers-2026-04.csv"
UTF-8 CSV with fallback
Content-Disposition: attachment; filename="resume-2026.csv"; filename*=UTF-8''r%C3%A9sum%C3%A9-2026.csv
Same-origin download link with attribute
<a href="/exports/customers.csv" download="local-name.csv">Download</a>
Remember:
- if the response header supplies a filename, MDN says that header filename takes priority over the
downloadattribute’s filename value downloadworks only for same-origin URLs, orblob:anddata:URLs (MDN element)
FAQ
What is the difference between filename and filename*?
filename is the older parameter and works best as a simple fallback. filename* is the standards-based form for encoded UTF-8 names.
Should I send both filename and filename*?
Usually yes. That is the safest practical pattern for compatibility and internationalized filenames.
Why does Safari sometimes show percent escapes literally?
Because percent escapes in the plain filename parameter are handled inconsistently across browsers. MDN explicitly warns about this.
Can the browser still change my filename?
Yes. Browsers may normalize path separators and make other filesystem-related adjustments.
Does the HTML download attribute always control the filename?
No. If the Content-Disposition header includes a filename, MDN says that header filename takes priority over the download attribute’s filename value.
Related tools and next steps
If you are working on downloadable CSVs, filenames, or browser-heavy export flows, these are the best next steps:
- CSV Validator
- CSV Format Checker
- CSV Delimiter Checker
- CSV Header Checker
- CSV Row Checker
- universal converter
- CSV tools hub
Final takeaway
Content-Disposition filename handling is one of those areas where “it works on my browser” is not a strong enough standard.
The safest practical approach is:
- keep
filenamesimple and ASCII-friendly - quote it when needed
- put the real UTF-8 name in
filename* - avoid percent escapes in plain
filename - remember that browsers may still normalize the final result
- test same-origin download flows separately from cross-origin ones
That discipline is usually enough to eliminate most filename surprises across browsers and make CSV export downloads feel much more polished.
About the author
Elysiate publishes practical guides and privacy-first tools for data workflows, developer tooling, SEO, and product engineering.