Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I try to download a file with wget and curl and it is rejected with a 403 error (forbidden).

I can view the file using the web browser on the same machine.

I try again with my browser's user agent, obtained by http://www.whatsmyuseragent.com. I do this:

wget -U 'Mozilla/5.0 (X11; Linux x86_64; rv:30.0) Gecko/20100101 Firefox/30.0' http://...


curl -A 'Mozilla/5.0 (X11; Linux x86_64; rv:30.0) Gecko/20100101 Firefox/30.0' http://...

but it is still forbidden. What other reasons might there be for the 403, and what ways can I alter the wget and curl commands to overcome them?

(this is not about being able to get the file - I know I can just save it from my browser; it's about understanding why the command-line tools work differently)


Thanks to all the excellent answers given to this question. The specific problem I had encountered was that the server was checking the referrer. By adding this to the command-line I could get the file using curl and wget.

The server that checked the referrer bounced through a 302 to another location that performed no checks at all, so a curl or wget of that site worked cleanly.

If anyone is interested, this came about because I was reading this page to learn about embedded CSS and was trying to look at the site's css for an example. The actual URL I was getting trouble with was this and the curl I ended up with is

curl -L -H 'Referer: http://css-tricks.com/forums/topic/font-face-in-base64-is-cross-browser-compatible/' http://cloud.typography.com/610186/691184/css/fonts.css

and the wget is

 wget --referer='http://css-tricks.com/forums/topic/font-face-in-base64-is-cross-browser-compatible/' http://cloud.typography.com/610186/691184/css/fonts.css

Very interesting.

share|improve this question
Pages that check referer are really annoying. The header is supposed to be optional and used for gathering statistics. –  aalizadeh Jun 29 at 10:59

3 Answers 3

up vote 18 down vote accepted

A HTTP request may contain more headers that are not set by curl or wget. For example:

  • Cookie: this is the most likely reason why a request would be rejected, I have seen this happen on download sites. Given a cookie key=val, you can set it with the -b key=val (or --cookie key=val) option for curl.
  • Referer (sic): when clicking a link on a web page, most browsers tend to send the current page as referrer. It should not be relied on, but even eBay failed to reset a password when this header was absent. So yes, it may happen. The curl option for this is -e URL and --referer URL.
  • Authorization: this is becoming less popular now due to the uncontrollable UI of the username/password dialog, but it is still possible. It can be set in curl with the -u user:password (or --user user:password) option.
  • User-Agent: some requests will yield different responses depending on the User Agent. This can be used in a good way (providing the real download rather than a list of mirrors) or in a bad way (reject user agents which do not start with Mozilla, or contain Wget or curl).

You can normally use the Developer tools of your browser (Firefox and Chrome support this) to read the headers sent by your browser. If the connection is not encrypted (that is, not using HTTPS), then you can also use a packet sniffer such as Wireshark for this purpose.

Besides these headers, websites may also trigger some actions behind the scenes that change state. For example, when opening a page, it is possible that a request is performed on the background to prepare the download link. Or a redirect happens on the page. These actions typically make use of Javascript, but there may also be a hidden frame to facilitate these actions.

If you are looking for a method to easily fetch files from a download site, have a look at plowdown, included with plowshare.

share|improve this answer
Maybe you should also add a note about the user agent? I've seen sites that reject user-agents like curl/wget; something like wget -U "Mozilla/5.0 (X11; Linux i686; rv:28.0) Gecko/20100101 Firefox/28.0" should fix that. –  user2064000 Jun 29 at 5:28
@user2064000 OP already mentions UA, but I will add it. –  Lekensteyn Jun 29 at 7:47
Another really perverse possibility would be that the server for some reason was configured to return 403 instead of 200 on success. –  kasperd Jun 29 at 8:19
This gave me the clue I needed. After trying cookies, I found the referrer to be the problem (now, if only that could be spelt properly!!!) –  starfry Jun 29 at 9:00

Depending on what you're asking for, it could be a cookie. With Firefox, you can do a right-click when you're on the page in question, "View Page Info". Choose "Security" icon, and then click "View Cookies" button.

For puzzling out cookies, the Firefox "Live HTTP Headers" plug-in is essential. You can see what cookies get set, and what cookies get sent back to the web server.

wget can work with cookies, but it's totally infuriating, as it doesn't give a hint that it didn't send cookies. Your best bet is to remove all related cookies from your browser, and go through whatever initial login or page viewing sequence it takes. Look at "Live HTTP Headers" for cookies, and for any POST or GET parameters. Do the first login step with wget using "--keep-session-cookies" and "--save-cookies" options. That will give you a cookie file you can look at with a text editor. Use wget --load-cookies with the cookie file for the next steps.

share|improve this answer
I tested without cookies in Firefox by opening a private browsing window and, as expected I got the 403 error. Interesting that you don't get the error in a new tab. In Chromium, a new tab returns the 403. –  starfry Jun 29 at 10:04
Incidentally, you can use the network tab of Firefox's dev tools to inspect sent and received cookies without any addons. Ditto for Chrome/Chromium. –  Bob Jun 29 at 13:57
@bob - yes I found that. It took me a few minutes as it wasn't something. Firebug has Copy as CURL now but it would be nice to see it the native tools too. –  starfry Jun 30 at 8:28

Just want to add to the above answers that you could use the "Copy as cURL" feature present in Chrome developer tools (since v26.0) and Firebug (since v1.12). You can access this feature right-clicking the request row in the Network tab.

share|improve this answer
This helped immensely, especially the tools in Chrome. When I tried in firefox, the request header after the 302 was all I could see. In Chromium I could see both and this gave me the info to solve the problem. –  starfry Jun 29 at 9:02
@starfry You need to tick Enable persistent logs on the settings tab of Firefox's dev tools to prevent it from clearing network logs on a redirect. Chrome has a similar option. Incidentally, "Copy as cURL" has been in Firefox Nightly/Aurora/Beta for a while now, and is due next major release (31.0). –  Bob Jun 29 at 14:02

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.