Content-Disposition header: attachment vs inline and file names (tested in Chrome)

One response header decides whether a file opens in the tab or downloads, and what it is called. Here is what Chrome did with each common form.

1. Download or show?

ResponseWhat Chrome did
text/plain, no Content-DispositionShowed it in the tab
text/plain + inline; filename="notes.txt"Showed it in the tab
text/plain + attachment; filename="notes.txt"Downloaded notes.txt
text/csv + inline; filename="report.csv"Downloaded report.csv. Chrome can't display CSV, so inline made no difference.

So attachment forces a download. inline only displays files the browser can show itself (text, images, PDF, HTML).

2. Which file name?

HeaderSaved as
attachment; filename="report.csv"report.csv
attachment (no name), URL /…/file.csvfile.csv (from the URL)
attachment; filename*=UTF-8''R%C3%A9sum%C3%A9%20%C3%A9t%C3%A9.csvRésumé été.csv
both filename="Resume ete.csv" and the filename* aboveRésumé été.csv (filename* wins)
filename="Résumé été.csv" as raw UTF-8 bytesRésumé été.csv in Chrome, but not standard
filename=my report.csv (unquoted, with a space)my report.csv
filename="../../etc/passwd.csv"_.._etc_passwd.csv (path removed)

3. What to send

Content-Disposition: attachment; filename="Resume ete.csv"; filename*=UTF-8''R%C3%A9sum%C3%A9%20%C3%A9t%C3%A9.csv

An ASCII filename as a fallback plus a percent-encoded UTF-8 filename* covers browsers and tools that only read one of them. Always quote filename, and strip " and \ from user-supplied names. Chrome tolerated an unquoted name with a space, but other clients may cut it at the space. In Python, urllib.parse.quote(name) builds the filename* value. In JavaScript, use encodeURIComponent(name).

Chrome removed the ../ path in our test, but don't rely on every client doing that: clean names on the server. The header only affects how the browser saves the file. The download attribute on a link (<a download="name.csv">) is the client-side alternative for same-origin files.

Frequently asked questions

What is the difference between inline and attachment?

attachment always downloads the file. inline shows it in the tab if the browser can display that type. In our Chrome test an inline CSV still downloaded, because Chrome can't show CSV.

How do I send a file name with accents or non-Latin characters?

Use filename*=UTF-8'' followed by the percent-encoded name, plus an ASCII filename fallback. Chrome saved Résumé été.csv correctly and preferred filename* when both were present.

Why is my Content-Disposition file name ignored?

Check that the header actually reaches the browser (DevTools → Network → Response Headers): proxies and CORS can hide it from JavaScript. Under the CORS rules, a cross-origin fetch() can only read it if the server sends Access-Control-Expose-Headers: Content-Disposition (not tested here).

Which name does the browser use without a filename?

The last part of the URL path. In our test, /attach-noname/file.csv saved as file.csv.

Written with AI assistance. Each header was served by a local test server on 2026-10-01 and opened by clicking a link in Chromium 153; the file names are the ones Chrome suggested. PlainHeaders is our extension; the other methods are free.