Introduction
For developers who live in the terminal, command-line API testing tools are indispensable. The two dominant tools in this space—cURL and HTTPie—serve similar purposes but with vastly different philosophies. cURL is the veteran Swiss Army knife available on virtually every system, while HTTPie is the modern, human-friendly alternative designed for developer happiness.
While graphical tools like Insomnia provide intuitive interfaces for API exploration, command-line tools excel in automation and scripting workflows.
cURL: The Universal Standard
Overview
cURL (Client URL) has been the de facto standard for command-line HTTP requests since 1997. It’s pre-installed on most Unix-like systems (Linux, macOS) and Windows 10+, making it universally accessible.
Basic Syntax
GET Request
curl https://api.example.com/users
POST Request
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name":"John","email":"john@example.com"}'
With Headers
curl -H "Authorization: Bearer token123" \
-H "Accept: application/json" \
https://api.example.com/profile
Save Response
curl -o response.json https://api.example.com/data
Advanced cURL Features
Follow Redirects
curl -L https://api.example.com/redirect
Include Headers in Output
curl -i https://api.example.com/users
Verbose Mode (Debugging)
curl -v https://api.example.com/users
File Upload
curl -F "file=@document.pdf" https://api.example.com/upload
Authentication
# Basic Auth
curl -u username:password https://api.example.com/secure
# Bearer Token
curl -H "Authorization: Bearer $TOKEN" https://api.example.com/api
HTTPie: The Human-Friendly Alternative
Overview
HTTPie (pronounced “aitch-tee-tee-pie”) is a modern command-line HTTP client with intuitive syntax, JSON support, and beautiful output formatting.
Basic Syntax
GET Request
http GET https://api.example.com/users
# or simply:
http https://api.example.com/users
POST Request
http POST https://api.example.com/users name=John email=john@example.com
With Headers
http https://api.example.com/profile \
Authorization:"Bearer token123" \
Accept:application/json
Download File
http --download https://api.example.com/file.pdf
Advanced HTTPie Features
JSON Syntax Sugar
# Simple key-value pairs become JSON
http POST https://api.example.com/users \
name=John \
age:=30 \
active:=true \
tags:='["developer","qa"]'
Form Data
http --form POST https://api.example.com/upload \
file@document.pdf \
description="Important document"
Sessions
# Create session
http --session=user1 POST https://api.example.com/login \
username=john password=secret
# Reuse session (cookies, headers preserved)
http --session=user1 GET https://api.example.com/profile
Pretty Printing
# Automatic syntax highlighting and formatting
http https://api.example.com/users
# Control output format
http --print=HhBb https://api.example.com/users
# H: request headers
# B: request body
# h: response headers
# b: response body
Side-by-Side Comparison
Syntax Comparison
Task | cURL | HTTPie |
---|---|---|
GET | curl https://api.com/users | http GET https://api.com/users |
POST JSON | curl -X POST -H "Content-Type: application/json" -d '{"name":"John"}' https://api.com/users | http POST https://api.com/users name=John |
Headers | curl -H "Auth: token" https://api.com | http https://api.com Auth:token |
Query Params | curl "https://api.com/search?q=test&page=1" | http GET https://api.com/search q==test page==1 |
File Upload | curl -F "file=@doc.pdf" https://api.com/upload | http --form POST https://api.com/upload file@doc.pdf |
Real Example: Create User
cURL
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer abc123" \
-d '{
"name": "Jane Doe",
"email": "jane@example.com",
"age": 28,
"active": true,
"roles": ["user", "moderator"]
}'
HTTPie
http POST https://api.example.com/users \
Authorization:"Bearer abc123" \
name="Jane Doe" \
email=jane@example.com \
age:=28 \
active:=true \
roles:='["user","moderator"]'
Scripting and Automation
Command-line tools are essential components of a comprehensive API testing strategy, particularly for automation and continuous integration workflows.
Bash Scripts with cURL
#!/bin/bash
# Configuration
API_BASE="https://api.example.com"
TOKEN="your-api-token"
# Function to make authenticated requests
api_call() {
local method=$1
local endpoint=$2
local data=$3
curl -X "$method" "$API_BASE$endpoint" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "$data"
}
# Login and get token
TOKEN=$(curl -X POST "$API_BASE/auth/login" \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"secret"}' | \
jq -r '.access_token')
# Use token for subsequent requests
api_call GET "/users"
api_call POST "/users" '{"name":"Test User","email":"test@example.com"}'
Bash Scripts with HTTPie
#!/bin/bash
API_BASE="https://api.example.com"
# Login and extract token
TOKEN=$(http POST "$API_BASE/auth/login" \
username=admin password=secret | \
jq -r '.access_token')
# Make authenticated requests
http GET "$API_BASE/users" "Authorization:Bearer $TOKEN"
http POST "$API_BASE/users" "Authorization:Bearer $TOKEN" \
name="Test User" email=test@example.com
CI/CD Integration
GitHub Actions with cURL
name: API Tests
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Test API Health
run: |
response=$(curl -s -o /dev/null -w "%{http_code}" https://api.example.com/health)
if [ $response -ne 200 ]; then
echo "API health check failed"
exit 1
fi
- name: Test User Creation
run: |
curl -X POST https://api.example.com/users \
-H "Authorization: Bearer ${{ secrets.API_TOKEN }}" \
-H "Content-Type: application/json" \
-d '{"name":"CI User","email":"ci@example.com"}' \
--fail-with-body
GitLab CI with HTTPie
api_tests:
stage: test
image: alpine:latest
before_script:
- apk add --no-cache httpie jq
script:
- http GET https://api.example.com/health --check-status
- |
http POST https://api.example.com/users \
Authorization:"Bearer $API_TOKEN" \
name="CI User" \
email=ci@example.com \
--check-status
Best Practices
Error Handling
cURL
# Check HTTP status code
http_code=$(curl -s -o /dev/null -w "%{http_code}" "$URL")
if [ "$http_code" -ne 200 ]; then
echo "Request failed with status $http_code"
exit 1
fi
# Fail on HTTP errors
curl --fail-with-body "$URL"
# Retry on failure
curl --retry 3 --retry-delay 5 "$URL"
HTTPie
# Exit with error on HTTP error statuses
http --check-status GET https://api.example.com/users
# Download with progress and resume
http --download --continue https://api.example.com/large-file.zip
Environment Variables
# .env file
API_BASE_URL=https://api.example.com
API_TOKEN=your-secret-token
cURL
source .env
curl -H "Authorization: Bearer $API_TOKEN" "$API_BASE_URL/users"
HTTPie
source .env
http "$API_BASE_URL/users" "Authorization:Bearer $API_TOKEN"
Response Processing
With jq (JSON processor)
# cURL + jq
curl https://api.example.com/users | jq '.[] | select(.active == true) | .email'
# HTTPie + jq (although HTTPie has built-in formatting)
http https://api.example.com/users | jq '.[] | select(.active == true) | .email'
Performance Comparison
Speed: cURL is generally faster (C-based) vs HTTPie (Python-based) Memory: cURL uses less memory Startup Time: cURL is nearly instant, HTTPie has slight Python overhead
For most API testing, the difference is negligible. Use HTTPie for interactive use, cURL for performance-critical automation.
When to Use Each
Use cURL When:
- ✓ Maximum compatibility required
- ✓ Scripting for production systems
- ✓ Minimal dependencies needed
- ✓ Performance is critical
- ✓ System doesn’t have HTTPie installed
Use HTTPie When:
- ✓ Interactive API exploration
- ✓ Developer experience matters
- ✓ Working primarily with JSON APIs
- ✓ Readability of scripts important
- ✓ Can install additional tools
Conclusion
Both cURL and HTTPie are excellent tools with different strengths:
cURL: Universal, fast, ubiquitous, powerful HTTPie: Modern, readable, user-friendly, JSON-focused
For most developers, the ideal setup is:
- HTTPie for daily interactive API testing
- cURL for scripts and automation where portability matters
Learn both—they complement each other perfectly in a comprehensive API testing toolkit. When comparing different API testing tools in 2025, command-line options like cURL and HTTPie remain essential alongside modern alternatives like REST Assured for Java-based automation.