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

FlagLong FormPurpose
-X--requestHTTP method (GET, POST, PUT, DELETE)
-H--headerAdd request header
-d--dataRequest body data
-v--verboseShow full request/response details
-s--silentHide progress bar
-o--outputSave response to file
-w--write-outCustom output format
-L--locationFollow redirects
-k--insecureSkip SSL verification
-u--userBasic auth (user:password)
-i--includeShow response headers
-I--headHEAD 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

  1. CRUD cycle with cURL: Create a post (POST), read it (GET), update it (PUT), then delete it (DELETE) using JSONPlaceholder
  2. Debug a request: Use -v to inspect all headers for a request to https://httpbin.org/get
  3. Measure performance: Time 5 different public API endpoints and compare response times using -w
  4. Write a health check script: Create a bash script that checks 3 endpoints and reports status codes
  5. 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 -w for performance measurement and -v for 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