If you’ve ever needed to test an API, debug a backend endpoint, or automate a web request without leaving the terminal, you’ve likely reached for cURL—the command-line Swiss Army knife for HTTP.
Pronounced “curl,” this open-source tool lets you send and receive data using a wide range of protocols—including HTTP, HTTPS, and FTP—directly from your shell. It’s lightweight, scriptable, and installed by default on most Unix-like systems (including macOS and Linux).
In this guide, you’ll learn how to use cURL to interact with RESTful APIs—covering GET, POST, PUT, DELETE, authentication, JSON payloads, file uploads, cookies, and debugging—all with real-world examples you can copy and adapt.
cURL Basics: The Core Syntax
At its simplest, cURL looks like this:
bash
1
curl [options] [URL]
But when working with APIs, you’ll almost always use flags to shape the request. Here are the most essential ones:
-Xor--request– Sets the HTTP method (GET,POST, etc.). Default isGETfor HTTP URLs.-Hor--header– Adds custom headers (e.g.,Content-Type,Authorization).-dor--data– Sends data in the request body (commonly used withPOST/PUT).-uor--user– Handles basic auth:-u username:password.-i– Includes response headers in the output.-vor--verbose– Shows full request/response details (great for debugging).-Lor--location– Automatically follows redirects (3xx responses).
💡 Pro tip: You can copy cURL commands directly from browser DevTools (Network tab → right-click request → “Copy as cURL”).
Common API Requests with cURL
✅ GET Request (with headers)
Fetch data—like a user profile—with custom headers:
bash
1
2
3
curl -H “Accept: application/json” \
-H “X-API-Key: your-secret-key” \
No -X GET needed—it’s the default.
✅ POST Request (with JSON body)
Create a new resource by sending structured data:
bash
1
2
3
4
curl -X POST \
-H “Content-Type: application/json” \
-d ‘{“name”: “Project Alpha”, “status”: “active”}’ \
https as://api.example.com/projects
⚠️ Note: Without
-H "Content-Type: application/json", cURL assumesapplication/x-www-form-urlencoded.
✅ PUT or PATCH (update a resource)
Update an existing record—use PUT for full replacement, PATCH for partial:
bash
1
2
3
4
curl -X PATCH \
-H “Content-Type: application/json” \
-d ‘{“email”: “updated@example.com”}’ \
✅ DELETE Request
Remove a resource:
bash
1
curl -X DELETE https://api.example.com/users/123
Often used with auth headers—add -H "Authorization: Bearer ..." if required.
Handling Authentication
🔑 Basic Auth
Let cURL handle Base64 encoding for you:
bash
1
curl -u admin:supersecret https://api.example.com/admin
This sends: Authorization: Basic YWRtaW46c3VwZXJzZWNyZXQ=
🔑 Bearer Token (OAuth, JWT, etc.)
Manually set the Authorization header:
bash
1
2
curl -H “Authorization: Bearer eyJhbGciOiJIUzI1NiIs…” \
Replace the token with your actual access token.
Advanced cURL Techniques
📤 Upload a File
Send a file as multipart/form-data (e.g., for image uploads):
bash
1
2
3
4
curl -X POST \
-F “file=@/path/to/photo.jpg” \
-F “description=Profile picture” \
The -F flag automatically sets the correct Content-Type and formats the payload.
🍪 Work with Cookies (for session-based APIs)
Save and reuse cookies across requests:
bash
1
2
3
4
5
# Log in and save cookies
curl -c cookies.txt -d “username=john&password=123” https://api.example.com/login
# Use saved cookies in next request
curl -b cookies.txt https://api.example.com/dashboard
-c→ save cookies to a file-b→ send cookies from a file or string
🔁 Follow Redirects
Some APIs (or legacy endpoints) redirect HTTP → HTTPS:
bash
1
curl -L http://api.example.com/data
The -L flag tells cURL to follow the Location header automatically.
📝 Send Multiple Headers
Stack -H flags as needed:
bash
1
2
3
4
curl -H “Authorization: Bearer token” \
-H “User-Agent: MyApp/2.1” \
-H “Accept-Language: en” \
Debugging API Calls Like a Pro
When things go wrong, cURL’s debug flags are invaluable:
-v(verbose): See request headers, response codes, redirects, and TLS handshake.--trace-ascii trace.log: Log a human-readable transaction dump.-i: Show response headers alongside the body (useful for checkingRate-LimitorCache-Control).
Common API Errors & Fixes:
401 Unauthorized→ Missing or invalid auth token. Double-check headers.400 Bad Request→ Malformed JSON, missing fields, or invalid URL. Validate your payload.403 Forbidden→ Valid credentials, but insufficient permissions.404 Not Found→ Wrong endpoint path or ID.
Use -v to compare your request against the API’s documentation—often the issue is a typo in a header name or JSON key.
Why Use cURL Instead of Postman or Insomnia?
GUI tools are great for complex workflows—but cURL shines when you need:
- Speed: Run a test in 2 seconds without opening an app
- Reproducibility: Paste the exact command into documentation or Slack
- Automation: Embed in shell scripts, cron jobs, or CI/CD pipelines
- Remote Debugging: Works over SSH when you can’t use a browser
Think of cURL as your terminal’s native HTTP client—minimal, reliable, and always there.
Final Tips for Success
- Always quote your JSON to avoid shell interpretation errors
- Use
--failto make cURL return a non-zero exit code on HTTP errors (great for scripts) - Store secrets in environment variables, not hardcoded in commands:bash1curl -H “Authorization: Bearer $API_TOKEN” …
Ready to Master the Command Line?
cURL isn’t just for testing—it’s a foundational skill for DevOps, backend development, and automation. Once you’re comfortable with it, you’ll find yourself reaching for it again and again.
💬 Got a tricky cURL issue? Share your command (with sensitive data redacted!) in dev communities like Stack Overflow or relevant subreddits. The community is always happy to help debug.
Happy cURLing! 🌀