Skip to the main text

Updated

Content-Disposition

Why a link downloads instead of opening in your browser

A link downloads instead of opening because of a header the server sent, not a setting on your machine. Either Content-Disposition: attachment told the browser to save the response rather than display it, or the Content-Type was generic enough — application/octet-stream — that the browser had nothing registered to draw it with. Both are set by whoever runs the site, and no browser setting overrides the first one. The way round it is to read the file rather than navigate to it, which is what Foretaste does from the link.

You clicked a .log file expecting to read it, and instead there is a file in your downloads folder. The same kind of link opened fine on another site yesterday. Nothing is misconfigured on your machine — the difference is one header, and it was set by somebody else.

01

The cause, in one line

The server sent this with the file:

Content-Disposition: attachment

That is an instruction to the browser: save this, do not display it. Your browser is doing exactly what it was told, and it will do it for a plain text file as readily as for an installer, because the header says nothing about what the file is. It is only about what to do with it.

Which is why the behaviour is inconsistent in a way that feels like a bug on your side. The same .csv displays on one host and downloads on another. A raw file view opens and its download button does not. One CI system shows you a build log in the browser and the next one hands you a file. Same format, same browser, different header.

The header often carries a filename too — filename="build-4821.log" — which is worth knowing because it is frequently the only place a name exists at all when the address is /artifacts/download?id=8812.

02

The other cause: a type the browser cannot draw

A file can download without any attachment header at all. If the server sends a Content-Type the browser has no renderer for, there is nothing to display and the download is the fallback. The usual culprit is the catch-all type servers reach for when they have not been configured to know any better:

Content-Type: application/octet-stream

It means "some bytes". A .docx served as application/octet-stream is the single most common real-world case, and a missing Content-Type behaves the same way. application/download, application/force-download and application/unknown all do it too.

This one is not an instruction, which is why it is worth telling apart from the first. Nobody asked the browser to save the file; it just had no other move. A reader that decides from the bytes rather than from the header is unaffected: Foretaste treats those six types as saying nothing, reads the first kilobyte over a ranged request, and matches it against real format signatures. A file whose type header is meaningless still opens as what it actually is.

How to tell which one you have

One request, no download:

curl -sI "https://example.com/the-link" | grep -i -E 'content-type|content-disposition'

Or open the browser's developer tools, the Network tab, click the link, and read the response headers on the request it makes.

  • You see Content-Disposition: attachment — cause one. The server asked for the download. No setting on your machine changes it.
  • You see a generic Content-Type and no disposition — cause two. The browser had nothing to draw it with.
  • You see both — common, and the disposition is the one doing the work.

Either way the fix is the same, and it is the next section: stop navigating to the address.

03

Two fixes that will not work

Both of these come up constantly when you search for this, and neither addresses it. Worth five sentences so you can stop looking.

Clearing "always open files of this type"

This is the most common suggestion and it is about the opposite half of the problem. That setting decides what happens after a file has been downloaded — whether your computer immediately opens it in an application. It has no bearing on whether the download happens at all. Turning it off changes nothing about a link that downloads when you wanted to read it.

Changing the header

Technically correct and usually not available to you. Most of the writing about Content-Disposition is aimed at whoever runs the server, because they are the only person who can change it. If the file is on a site you do not operate, that advice ends the conversation rather than answering it.

The header is not the thing to fight. The navigation is, because the instruction only applies to a browser being pointed at the address.

04

Read the file instead of navigating to it

Right-click the link and choose Open with Foretaste. It requests the same address your browser would have, reads the bytes in its own tab, and puts the contents on screen. The attachment instruction never has a navigation to act on, so it does not fire — not because it has been stripped or overridden, but because nothing is being navigated.

Foretaste does read that header, for one thing: the filename in it. That is how a link with no name and no extension still arrives called build-4821.log rather than download.

What you get for a text file, a log or a config file:

  • The file, syntax-highlighted. Markdown renders, with a switch back to the source. JSON opens as a tree you can collapse.
  • Only the lines containing a word, when you want that rather than the whole thing.
  • On something shaped like a log, a row of level buttons carrying the count of each, so you can show one level at a time. The row reads something like INFO 312, WARN 12, ERROR 4 — numbers that illustrate the interface rather than any file we have counted. Each count comes from your own file, read in your browser. It takes the first level word on each line, so an info line reporting a retry after an error stays an info line.

The honest limit: the first 5,000,000 bytes and 20,000 lines, and it tells you on screen where it stopped rather than quietly trailing off. Reading further is the paid plan; everything else described on this page is free.

Highlighting is not validation, and a .env file is shown exactly as written. What you see for text, code and data has the rest of it.

05

The case this comes up in most

Build artifacts. A failed job, a log you want to look at once, and a link that hands you a file instead of showing it — so you download it, open it in an editor, read four lines, and now it is in your downloads folder forever. Multiply by every red build.

The same applies to a directory index full of exports, a bug report with three attached logs, and any page where you want to read one file and keep none of them. If there are several, Foretaste can list every file on the page first, and ask how big each one is before you open anything.

The other place it happens constantly is a notebook. A .ipynb on a git host or a course page is often served as an attachment, so clicking it hands you a file you then need Jupyter, or an editor, or a converter to read — when all you wanted was to see whether the plots came out. Foretaste reads the same address and draws the notebook: the markdown rendered, the code highlighted, and the outputs the author saved sitting under the cells that produced them. Nothing in it runs. It is read whole, because a notebook is JSON with its pictures inside it, and the meter under the file says so rather than claiming a saving it did not make.

06

Reading it is free. Reading all of it is Pro.

Opening the file, reading it, searching it and saving it are free at any size. What a plan changes is how far into a very large one the view goes before it stops and says so: 5 MB becomes 50 MB, and 20,000 lines become 200,000.

07

When this will not work either

The site can refuse the request. A server that checks whether a request came from its own pages will answer 403, and a sign-in page or a bot check is a question aimed at a person. Foretaste says which of those happened and offers to save the file through the browser instead, which usually gets through. Which refusals are which, and what each one actually wants from you.

The file may not be what the link says. A header can name a file report.pdf while the bytes are something else entirely. Foretaste checks the leading bytes against the signatures real formats begin with and tells you when the two disagree — what a file really is, before you open it. It is not antivirus and it does not say whether anything is safe.

And this is not a way around a download you are meant to make. If a site wants you signed in, Foretaste offers to open the page so you can sign in. It has nothing that gets past a no.

The questions people ask

Why does a link download instead of opening in the browser?

For one of two reasons, both of them headers the server sent. Either Content-Disposition: attachment told the browser to save the response rather than display it, and the browser obeys that regardless of what the file actually is; or the Content-Type was generic enough - application/octet-stream is the usual one - that the browser had nothing registered to draw it with, so downloading was the only thing left. A .txt, .log, .csv or .json file that opens fine on one site and downloads on another is usually the same file type with a different header in front of it.

Why does a file download when there is no Content-Disposition header?

Because the Content-Type is one the browser cannot render. application/octet-stream literally means "some bytes", and a server that has not been configured to know better sends it for everything; a missing Content-Type behaves the same way. application/download, application/force-download and application/unknown do it too. Nothing has instructed the browser to save the file here - it simply had no way to display it, which is why this cause needs a different diagnosis from the attachment header even though the symptom is identical.

How can I tell which of the two is causing it?

Read the response headers without downloading the file. On a command line, curl -sI "https://example.com/the-link" prints them; in a browser, open the developer tools, select the Network tab, click the link and read the headers on the request it makes. Content-Disposition: attachment means the server asked for the download. A generic Content-Type with no disposition means the browser had nothing to draw the file with. If both are present, the disposition is the one doing the work.

Why does clearing "always open files of this type" not fix it?

Because that setting does something else. It controls what happens to a file after it has already been downloaded - whether your computer opens it in an application automatically. It has no effect on whether the download happens. It is the advice most search results give for this problem and it addresses the wrong half of it.

Can you open a file that has Content-Disposition: attachment on it?

Yes, if something reads the file instead of navigating to it. Foretaste fetches the address and reads the bytes inside its own tab, so the attachment instruction never has a navigation to act on. The header is still read, but only for the filename it carries, which is often the only place a name exists when the address is something like /download?id=8812.

How much of a large log file will it show?

The first 5,000,000 bytes and the first 20,000 lines, and it says on screen where it stopped rather than trailing off. That is the free limit; the paid plan reads ten times as much. Everything else on this page is free.