Skip to content
Laviyx Learn

Try

Linux and Bash course menu

curl Tutorial: Call APIs and Download Files from the Terminal

Use curl to make GET and POST requests, send JSON, view headers and status codes, follow redirects, download files with curl and wget, and read JSON with jq.

Intermediate5 min readUpdated
On this page

curl sends web requests from the terminal. Developers use it to test APIs, health-check servers and write scripts. In this lesson a small web server is running on this machine, on port 8000.

A simple request#

Terminal
curl -s http://localhost:8000/info.json
Output
{"name": "Laviyx Learn", "courses": 16, "free": true}

-s hides the progress bar.

Headers and status codes#

-I asks for headers only:

Terminal
curl -sI http://localhost:8000/info.json | head -n 4
Output
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.12.3
Date: Thu, 05 Nov 2026 06:24:12 GMT
Content-type: application/json

-v shows the whole conversation, including what curl sent, and is the best tool for debugging. To get only the status code, use -w:

Terminal
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8000/info.json
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8000/missing
Output
200
404

-o /dev/null throws away the body. This pair of options is common in health-check scripts.

Reading JSON with jq#

jq extracts values from JSON. Install it with sudo apt install jq:

Terminal
curl -s http://localhost:8000/info.json | jq .
curl -s http://localhost:8000/info.json | jq -r .name
Output
{
  "name": "Laviyx Learn",
  "courses": 16,
  "free": true
}
Laviyx Learn

-r prints plain text, without quotes.

Send data#

A demo server echoes back what it receives, so that you can see what curl sent:

Terminal
curl -s -X POST http://localhost:9000/users \
  -H "Content-Type: application/json" \
  -d '{"name": "Asha"}'
Output
POST /users [application/json] [None] {"name": "Asha"}
OptionMeaning
-X POSTThe HTTP method
-H "Name: value"Add a header
-d 'data'The request body; this makes it a POST by default
-d @file.jsonSend a file as the body

Authentication#

APIs usually want a token in a header. Keep it in a variable, not in the script:

Terminal
export API_TOKEN=example-token
curl -s -X DELETE http://localhost:9000/users/7 -H "Authorization: Bearer $API_TOKEN"
Output
DELETE /users/7 [None] [Bearer example-token]

Download files#

-o chooses a name, -O keeps the remote name, and -L follows redirects, which you nearly always want:

Terminal
curl -sL -o page.html http://localhost:8000/index.html
curl -sO http://localhost:8000/index.html
ls *.html
Output
index.html
page.html

wget is an alternative that is built for downloading:

Terminal
wget https://example.com/file.zip

Timeouts#

Scripts should never wait forever:

Terminal
curl -s --max-time 2 --retry 1 -o /dev/null -w "%{http_code}\n" http://localhost:8000/
Output
200

Common mistakes#

Practice#

Practice exercise

Use curl and jq to print the value of courses from /info.json, then show that curl -f exits with a failure for /missing by printing its exit code.

Show solution
Terminal
curl -s http://localhost:8000/info.json | jq .courses
curl -sf http://localhost:8000/missing
echo "Exit code: $?"
Output
16
Exit code: 22

Key takeaway#

Next: SSH and Copying Files to Servers.

Finished this lesson?