I'm using curl
at the command line on Linux to issue HTTP requests. The response bodies are printed to standard out, which is fine, but I can't see from the man page how to get curl to print the HTTP status code from the response (404, 403 etc). Is this possible?
19 Answers
This should work for you if the web server is able to respond to HEAD requests (this will not perform a GET
request):
curl -I http://www.example.org
As an addition, to let cURL follow redirects (3xx statuses) add -L
.
-
221NB:
curl -I
does a HEAD HTTP request, which can be problematic for testing the HTTP status code for some web application servers and services Sep 6, 2012 at 17:32 -
31And to get just the status number, pipe it to
head -n 1|cut -d$' ' -f2
– BenubirdJul 17, 2013 at 11:33 -
51Don't forget to redirect curl's stderr:
curl -I http://www.example.org 2>/dev/null | head -n 1 | cut -d$' ' -f2
. Add -L to curl if you need the final status after redirects. Jul 24, 2014 at 21:16 -
62
-
4Forwarding stderr to /dev/null is not neccessary if you only want to suppress the progress bar - use
-s
switch for that.– galvaDec 12, 2016 at 9:39
A more specific way to print out just the HTTP status code is something along the lines of:
curl -s -o /dev/null -w "%{http_code}" http://www.example.org/
A lot easier to work with in scripts, as it doesn't require any parsing :-)
The parameter -I
might be added to improve response load performance. This will change the call to a HEAD
call which will fetch response overhead only, without the body.
Note: %{http_code}
returns on first line of HTTP payload (available variables for the -w
option on the curl
documentation page)
i.e.:
curl -s -o /dev/null -I -w "%{http_code}" http://www.example.org/
-
81-w "%{http_code}" is the bit that prints the status code. You can add a newline or two in there to separate the code from the body (-w "\n\n%{http_code}\n") Jan 11, 2014 at 8:33
-
17Wow, this
/dev/null
thing even works in the Windows version of curl that I'm using.– Uwe KeimJan 30, 2015 at 6:53 -
3I believe this downloads the entire file even though it all goes to /dev/null, so not ideal for checking the status code for huge files.
httping -c 1 -s -G -m
issues a GET and doesn't download the whole file, although I realise this question is specifically about curl.– RomanStDec 13, 2015 at 23:59 -
81FYI:
-s
= Don't show download progress,-o /dev/null
= don't display the body,-w "%{http_code}"
= Write http response code to stdout after exit.– Ajedi32Jul 19, 2016 at 16:59 -
3
You can print the status code, in addition to all the headers by doing the following:
curl -i http://example.org
The good thing about -i
is that it works with -X POST
as well.
-
80
-
18Maybe obvious, but
-i
does work with any HTTP method, not justGET
andPOST
... :)– macOct 20, 2014 at 10:35 -
7the best answer as it makes curl output both headers and body, making it suitable for most of the tasks when used in a script Aug 31, 2015 at 19:52
-
12This is the best answer, and can be used in conjunction with
-s
(don't show progress meter or error messages) and-S
(do show error messages after all) Feb 23, 2017 at 19:10 -
5Sorry if one wants only the HTTP status code this answer is not doing that. pvandenberk's answer that sends the output to /dev/null` does output only the three digit HTTP code by then requesting only the HTTP code in the format output. Feb 20, 2021 at 14:20
If you want to see the header as well as the result you can use the verbose option:
curl -v http://www.example.org
curl --verbose http://www.example.org
The status will appear in the header. E.g.
< Date: Tue, 04 Nov 2014 19:12:59 GMT
< Content-Type: application/json; charset=utf-8
< Status: 422 Unprocessable Entity
If you want to capture the HTTP status code in a variable, but still redirect the content to STDOUT, you must create two STDOUTs. You can do so with process substitution >() and command substitution $().
First, create a file descriptor 3
for your current process' STDOUT with exec 3>&1
.
Then, use curl's -o
option to redirect the response content to a temporary fifo using command substitution, and then within that command substitution, redirect output back to your current process STDOUT file descriptor 3
with -o >(cat >&3)
.
Putting it all together in bash
3.2.57(1)-release
(standard for macOS
):
# creates a new file descriptor 3 that redirects to 1 (STDOUT)
exec 3>&1
# Run curl in a separate command, capturing output of -w "%{http_code}" into HTTP_STATUS
# and sending the content to this command's STDOUT with -o >(cat >&3)
HTTP_STATUS=$(curl -w "%{http_code}" -o >(cat >&3) 'http://example.com')
Note that this doesn't work in /bin/sh
as SamK noted in the comments below.
-
7
-
4Now how, in turn, can I redirect the output to another variable? Mar 12, 2015 at 1:46
-
1The output is in
STDOUT
, so you should be able to redirect output from the command to anywhere you like just like a regular command. I haven't tested this though. Jul 21, 2015 at 3:10 -
2
-
1good answer, you can also redirect to a real file and cat it later if you want portability of shells Feb 8, 2019 at 9:40
Redefine curl output:
curl -sw '%{http_code}' http://example.org
Can be used with any request type.
-
-
This is the most straightforward answer -- no odd workarounds with file descriptors, hacky processing of human-readable text with
sed
, extra unwanted text output…– ijosephJul 7, 2022 at 4:12
Status code ONLY
[0]$ curl -LI http://www.example.org -o /dev/null -w '%{http_code}\n' -s
[0]$ 200
All credit to this GIST
-
2This one works like a charm, specially when using curl between Docker containers. I use it like this in PHP:
exec("curl -LI "my service name"/"the file I'm looking the HTTP code for" -o /dev/null -w '%{http_code}\n' -s")
(e.g.:exec("curl -LI static/someimage.jpg -o [...]
where "static" is the service name defined in Docker Compose). Thanks! Aug 19, 2021 at 20:28 -
I would get rid of the -I so it does a normal GET instead of a HEAD request. Mar 9 at 18:32
This is a painful curl --fail
limitation. From man curl
:
-f, --fail (HTTP) Fail silently (no output at all) on server errors
But there is no way to get both the non-zero return code AND the response body in stdout.
Based on pvandenberk's answer and this other very useful trick learned on SO, here is a workaround :
curl_with_error_code () {
_curl_with_error_code "$@" | sed '$d'
}
_curl_with_error_code () {
local curl_error_code http_code
exec 17>&1
http_code=$(curl --write-out '\n%{http_code}\n' "$@" | tee /dev/fd/17 | tail -n 1)
curl_error_code=$?
exec 17>&-
if [ $curl_error_code -ne 0 ]; then
return $curl_error_code
fi
if [ $http_code -ge 400 ] && [ $http_code -lt 600 ]; then
echo "HTTP $http_code" >&2
return 127
fi
}
This function behaves exactly as curl
, but will return 127 (a return code non-used by curl
) in case of a HTTP code in the range [400, 600[.
-
3Agreed, not being able to see the error output is a painful limitation of the otherwise very handy --fail. How can you diagnose a REST api failure without seeing the error output? It's so unfortunate that the curl maintainer bagder stubbornly insists on not providing a --fail-but-show-error. github.com/curl/curl/issues/1978– jamshidMay 13, 2018 at 23:33
-
As stated in documentation, it doesn't work for 401 and 407 HTTP code :( Aug 29, 2019 at 8:47
-
2
This will send a request to url, get only the first line of the response, split it on blocks and select the second one.
It contains the response code
curl -I http://example.org 2>/dev/null | head -n 1 | cut -d$' ' -f2
-
1Can you explain what this code does and how it addresses the problem given by the OP? Unexplained code can appear untrusted and dangerous to users.– bwDracoJul 16, 2015 at 1:58
-
2Sure, we send a request to url, get only the first line of the response, split it on blocks and select the second one. It contains the response code that OP is looking for. Jul 20, 2015 at 22:01
For a POST request, the following worked:
curl -w 'RESP_CODE:%{response_code}' -s -X POST --data '{"asda":"asd"}' http://example.com --header "Content-Type:application/json"|grep -o 'RESP_CODE:[1-4][0-9][0-9]'
Use the following cURL command and pipe it to grep like so:
$ curl -I -s -L http://example.com/v3/get_list | grep "HTTP/1.1"
Here's what each flag does:
-I
: Show only response headers-s
: Silent - Don't show progress bar-L
: FollowLocation:
headers
Here is a link to HTTP status codes.
Run from the command line. This curl runs in silent mode, follows any redirects, get the HTTP headers. grep will print the HTTP status code to standard output.
An example of how to use the response codes. I use this to re-download Geolite databases only if they have changed (-z
) & also following redirects (-L
):
url=http://example.com/file.gz
file=$(basename $url)
response=$(curl -L -s -o $file -z $file $url -w "%{http_code}")
case "$response" in
200) do_something ;;
301) do_something ;;
304) printf "Received: HTTP $response (file unchanged) ==> $url\n" ;;
404) printf "Received: HTTP $response (file not found) ==> $url\n" ;;
*) printf "Received: HTTP $response ==> $url\n" ;;
esac
Here is some curl command that is using GET
and that returns the HTTP code.
curl -so /dev/null -w '%{response_code}' http://www.example.org
Please remember that the approach below is using HEAD
, which is faster but it may not work well with some web less compliant HTTP servers.
curl -I http://www.example.org
curl -so -i /dev/null -w "%{http_code}" http://www.any_example.com
This will return the following information:
- response data, if any data is returned by API like error
- status code
-
This doesn't follow redirects. This existing answer is better superuser.com/a/442395/475508 Apr 10, 2017 at 18:16
-
Split output content to stdout
and HTTP status code to stderr
:
curl http://www.example.org -o >(cat >&1) -w "%{http_code}\n" 1>&2
If only HTTP status code is desired to stderr, --silent
can be used:
curl --silent http://www.example.org -o >(cat >&1) -w "%{http_code}\n" 1>&2
The desired stream can then be picked by redirecting unwanted one to /dev/null
:
$ (curl --silent http://www.example.org -o >(cat >&1) -w "%{http_code}" 1>&2) 1>/dev/null
200
$ (curl --silent http://www.example.org -o >(cat >&1) -w "%{http_code}" 1>&2) 2>/dev/null
<!doctype html>
...
Note that for the second redirection to behave as desired, we need to run the curl command in subshell.
-
1
-
@Bruno, I changed the example from superuser.com/revisions/1444693/2, as I think the
/tmp/out
/tmp/err
files can cause unexpected results if run parallel.– JaakkoOct 8, 2019 at 8:13
The OP wants to know the status code. Often when downloading a file you also want to get a feel of it's size so I'm using curl first to show status code and size of file and then shut off verbose and direct file to the place and name I want:
curl -R -s -S -w "\nhttp: %{http_code} %{size_download}\n" -o /Users/myfiles/the_local_name.html http://archive.onweb.com/the_online_name.html
Then I wait for the finishing of curl
wait ${!}
before I run the next command. The above when used in a script of many commands like above gives a nice response like:
http: 200 42824
http: 200 34728
http: 200 35452
Please note that -o in curl needs to be followed by the full path of the file + name of file. This allows you thusly to save files in a sensible name structure when you d/l them with curl. Also note that -s and -S used together silence the output but does show errors. Note also that -R tries to set the file timestamp to that of the web file.
My answer is based on what @pvandenberk originally suggested, but in addition it actually saves the file somewhere, instead of merely directing to /dev/null.
$ curl -kv https://www.example.org 2>&1 | grep -i 'HTTP/1.1 ' | awk '{print $3}'| sed -e 's/^[ \t]*//'
- 2>&1: error is stored in output for parsing
- grep: filter the response code line from output
- awk: filters out the response code from response code line
- sed: removes any leading white spaces
There is another way by using Powershell command which is alias to curl.exe Just type the following:
(Invoke-WebRequest -Uri https://your.website).StatusCode
In Windows PowerShell:
curl https:\\www.example.org -Method HEAD
It's really just an alias for Invoke-WebRequest
though.
-i
flag, as incurl -i https://www.example.com/
, is probably what you want, as per superuser.com/a/514798/190188curl -IL http://www.example.com | grep "^HTTP\/"
?