Why Learn cURL?
cURL (Client URL) is a command-line tool for transferring data using various protocols. It comes pre-installed on macOS and most Linux distributions, and is available for Windows. Every QA engineer should know cURL because:
- It’s universal — available on every server, container, and CI/CD runner
- It’s scriptable — easily integrated into shell scripts and pipelines
- It’s the lingua franca — API documentation often provides cURL examples
- No installation needed — unlike Postman, it’s already on your machine
- It’s precise — you control every aspect of the request
Checking Your Installation
curl --version
# curl 8.7.1 (x86_64-apple-darwin23.0) ...
Basic cURL Commands
GET Request
# Simple GET
curl https://jsonplaceholder.typicode.com/posts/1
# GET with headers
curl -H "Accept: application/json" \
-H "Authorization: Bearer token123" \
https://api.example.com/users
POST Request
# POST with JSON body
curl -X POST \
-H "Content-Type: application/json" \
-d '{"title": "New Post", "body": "Content", "userId": 1}' \
https://jsonplaceholder.typicode.com/posts
# POST with form data
curl -X POST \
-d "username=admin&password=secret" \
https://api.example.com/login
PUT and PATCH
# PUT — replace entire resource
curl -X PUT \
-H "Content-Type: application/json" \
-d '{"title": "Updated", "body": "New content", "userId": 1}' \
https://jsonplaceholder.typicode.com/posts/1
# PATCH — partial update
curl -X PATCH \
-H "Content-Type: application/json" \
-d '{"title": "Only Title Changed"}' \
https://jsonplaceholder.typicode.com/posts/1
DELETE
curl -X DELETE https://jsonplaceholder.typicode.com/posts/1
Essential cURL Flags
| Flag | Long Form | Purpose |
|---|---|---|
-X | --request | HTTP method (GET, POST, PUT, DELETE) |
-H | --header | Add request header |
-d | --data | Request body data |
-v | --verbose | Show full request/response details |
-s | --silent | Hide progress bar |
-o | --output | Save response to file |
-w | --write-out | Custom output format |
-L | --location | Follow redirects |
-k | --insecure | Skip SSL verification |
-u | --user | Basic auth (user:password) |
-i | --include | Show response headers |
-I | --head | HEAD request (headers only) |
Debugging with cURL
Verbose Output
The -v flag is your best friend for debugging:
curl -v https://jsonplaceholder.typicode.com/posts/1
Output shows:
>— request headers sent<— response headers received*— connection info and SSL details
Response Headers Only
# Show response headers with body
curl -i https://jsonplaceholder.typicode.com/posts/1
# Show only headers (HEAD request)
curl -I https://jsonplaceholder.typicode.com/posts
Timing Requests
curl -w "\nHTTP Code: %{http_code}\nTotal Time: %{time_total}s\nDNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTTFB: %{time_starttransfer}s\n" \
-s -o /dev/null \
https://jsonplaceholder.typicode.com/posts
This shows performance metrics without the response body.
Authentication with cURL
API Key
# In header
curl -H "X-API-Key: your-api-key" https://api.example.com/data
# As query parameter
curl "https://api.example.com/data?api_key=your-api-key"
Basic Auth
curl -u username:password https://api.example.com/users
# Equivalent to: -H "Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ="
Bearer Token (JWT/OAuth)
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
https://api.example.com/protected
Advanced Techniques
Sending Files
# Upload a file
curl -X POST \
-F "file=@photo.jpg" \
-F "description=Profile photo" \
https://api.example.com/upload
# Send JSON from a file
curl -X POST \
-H "Content-Type: application/json" \
-d @payload.json \
https://api.example.com/users
Saving Responses
# Save to file
curl -o response.json https://api.example.com/data
# Save only if successful
curl -f -o response.json https://api.example.com/data
Scripting with cURL
#!/bin/bash
# Simple API health check script
BASE_URL="https://api.example.com"
ENDPOINTS=("/health" "/users" "/posts")
for endpoint in "${ENDPOINTS[@]}"; do
status=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL$endpoint")
if [ "$status" -eq 200 ]; then
echo "OK: $endpoint ($status)"
else
echo "FAIL: $endpoint ($status)"
fi
done
Converting Between cURL and Postman
Postman to cURL: Click the </> Code icon in Postman and select cURL.
cURL to Postman: Click Import in Postman, paste your cURL command, and Postman builds the request.
Using jq for JSON Processing
# Pretty-print JSON response
curl -s https://jsonplaceholder.typicode.com/posts | jq '.'
# Extract specific field
curl -s https://jsonplaceholder.typicode.com/posts/1 | jq '.title'
# Filter array
curl -s https://jsonplaceholder.typicode.com/posts | jq '.[0:3] | .[].title'
Hands-On Exercise
- CRUD cycle with cURL: Create a post (POST), read it (GET), update it (PUT), then delete it (DELETE) using JSONPlaceholder
- Debug a request: Use
-vto inspect all headers for a request tohttps://httpbin.org/get - Measure performance: Time 5 different public API endpoints and compare response times using
-w - Write a health check script: Create a bash script that checks 3 endpoints and reports status codes
- Practice jq: Fetch posts from JSONPlaceholder and extract only titles using jq
Key Takeaways
- cURL is universal, scriptable, and available everywhere — essential knowledge for any QA engineer
- Master the key flags:
-X(method),-H(headers),-d(data),-v(debug),-s(silent),-o(output) - Use
-wfor performance measurement and-vfor full request/response debugging - cURL integrates naturally into shell scripts, CI/CD pipelines, and automated health checks
- Combine cURL with jq for powerful JSON processing from the command line