Getting Started with cURL
What is cURL
cURL is a command-line tool. It lets you to send request to server and receive data from server, such as fetching a webpage or interacting with API directly from terminal.
Why programmers need cURL
Programmers can have direct and raw access with servers right from terminal with any GUI, revealing responses, status codes, headers, etc.
Making your first request using cURL
Open you terminal and typein curl https://example.com
~ $ curl https://example.com
<!doctype html><html lang="en"><head><title>Example Domain</title><meta name="viewport" content="width=device-width, initial-scale=1"><style>body{background:#eee;width:60vw;margin:15vh auto;font-family:system-ui,sans-serif}h1{font-size:1.5em}div{opacity:0.8}a:link,a:visited{color:#348}</style><body><div><h1>Example Domain</h1><p>This domain is for use in documentation examples without needing permission. Avoid use in operations.<p><a href="https://iana.org/domains/example">Learn more</a></div></body></html>
cURL with -i flag curl -i https://example.com reveals full headers, incuding status code 200.
~ $ curl -i https://example.com
HTTP/2 200
date: Wed, 21 Jan 2026 01:43:56 GMT
content-type: text/html
cf-ray: 9c131f9f9a143d2e-BLR
last-modified: Tue, 20 Jan 2026 21:08:27 GMT
allow: GET, HEAD
accept-ranges: bytes
age: 12864
cf-cache-status: HIT
server: cloudflare
<!doctype html><html lang="en"><head><title>Example Domain</title><meta name="viewport" content="width=device-width, initial-scale=1"><style>body{background:#eee;width:60vw;margin:15vh auto;font-family:system-ui,sans-serif}h1{font-size:1.5em}div{opacity:0.8}a:link,a:visited{color:#348}</style><body><div><h1>Example Domain</h1><p>This domain is for use in documentation examples without needing permission. Avoid use in operations.<p><a href="https://iana.org/domains/example">Learn more</a></div></body></html>
Here, we get complete headers followed by a html webpage, mimicking browser.
Understanding Request and Response
Simple Request response cycle :
- A Client (Browser, cURL or app) sends request (with request headers and body) to server.
- Request travels to server that hosts webpage or API.
- Server processes request and returns a response to Client with Status Code (Such as 200 for OK, 400, 500, etc), response headers (extra info) and actual response body (such as html, json or image etc).
- Client uses that response and do whatever it is supposed to do such as rendering html on browser or using response data in app or printing on terminal.
For understanding complete request and response cycle, following command is useful : curl -v https://example.com. (v - verbose).
~ $ curl -v https://example.com
* Host example.com:443 was resolved.
* IPv6: 2606:4700:9ae2:8c7c:3342:0:ccc4:a209
* IPv4: 104.18.26.120, 104.18.27.120
* Trying [2606:4700:9ae2:8c7c:3342:0:ccc4:a209]:443...
* Connected to example.com (2606:4700:9ae2:8c7c:3342:0:ccc4:a209) port 443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/cert.pem
* CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificate:
* subject: CN=example.com
* start date: Dec 16 19:39:32 2025 GMT
* expire date: Mar 16 18:32:44 2026 GMT
* subjectAltName: host "example.com" matched cert's "example.com"
* issuer: C=US; O=SSL Corporation; CN=Cloudflare TLS Issuing ECC CA 3
* SSL certificate verify ok.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://example.com/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: example.com]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.7.1]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: example.com
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/2 200
< date: Wed, 21 Jan 2026 01:49:00 GMT
< content-type: text/html
< cf-ray: 9c13270fd8c947c0-BOM
< last-modified: Tue, 20 Jan 2026 21:08:27 GMT
< allow: GET, HEAD
< accept-ranges: bytes
< age: 13169
< cf-cache-status: HIT
< server: cloudflare
<
<!doctype html><html lang="en"><head><title>Example Domain</title><meta name="viewport" content="width=device-width, initial-scale=1"><style>body{background:#eee;width:60vw;margin:15vh auto;font-family:system-ui,sans-serif}h1{font-size:1.5em}div{opacity:0.8}a:link,a:visited{color:#348}</style><body><div><h1>Example Domain</h1><p>This domain is for use in documentation examples without needing permission. Avoid use in operations.<p><a href="https://iana.org/domains/example">Learn more</a></div></body></html>
In this verbose view, we can see detailed request-response cycle including DNS resolution, TLS handshake, headers exchange and html body delivery. It shows every step that can not be viewed in browser.
Using cURL to talk to APIs
cURL can talk to APIs with http request, with various methods such as GET and POST.
We shall utilise public API for demonstration.
GET method (reading or fetching data)
~ $ curl "https://api.freeapi.app/api/v1/public/randomjokes?limit=10&query=science&inc=categories%252Cid%252Ccontent&page=1"
{"statusCode":200,"data":{"page":1,"limit":10,"totalPages":1,"previousPage":false,"nextPage":false,"totalItems":4,"currentPageItems":4,"data":[{"categories":["science"],"id":140,"content":"Science Fact: Roundhouse kicks are comprised primarily of an element called Chucktanium."},{"categories":[],"id":456,"content":"All science students maybe aware about the fact that picochuck is the unit of manliness in the International System of Units (SI). An average man measures about 0.00073 pc. Chuck Norris measures 39,372 petachucks."},{"categories":[],"id":1073,"content":"The 7 wonders of the world were actually Chuck Norris' science fair projects. And Chuck Norris is the 8th wonder of the world."},{"categories":[],"id":1269,"content":"Larry the Cable Guy was a nuclear science physics professor at MIT for only 3 seconds more after he called Chuck Norris' mother a \"slutty beatch of a crack whore\"."}]},"message":"Random jokes fetched successfully","success":true}%
POST method (for sending data to server)
~ $ curl -d "hi" https://httpbin.org/post
{
"args": {},
"data": "",
"files": {},
"form": {
"hi": ""
},
"headers": {
"Accept": "*/*",
"Content-Length": "2",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "curl/8.7.1",
"X-Amzn-Trace-Id": "Root=1-6972bf37-19e5eaee0489d67632d84838"
},
"json": null,
"origin": "152.58.61.145",
"url": "https://httpbin.org/post"
}
This send "hi" as form data to `https://httpbin.org/post` and that form data is sent back by server as json.
Common mistakes beginners make with cURL
- Using URLs that contains '?' and '&' without quotes
- Forgetting HTTPS/443: curl http://example.com:443 fails. Fix: Use https:// prefix.
- verbose debugging : add -v argument for verbose debugging if see TLS or DNS issues