I was testing an API and needed to read the JSON response. Piping curl to jq makes it readable.
Basic request with formatted output:
curl 'https://api.example.com/data' | jq
Quiet mode (no progress bar):
curl -s 'https://api.example.com/data' | jq
Extract a specific field:
curl -s 'https://api.example.com/data' | jq '.name'
Extract from an array:
curl -s 'https://api.example.com/items' | jq '.[0].name'
Filter array items:
curl -s 'https://api.example.com/items' | jq '.[] | select(.status == "active")'
POST request:
curl -s -X POST 'https://api.example.com/data' \
-H 'Content-Type: application/json' \
-d '{"name": "test"}' | jq
With auth header:
curl -s -H "Authorization: Bearer $TOKEN" \
'https://api.example.com/data' | jq
Common jq filters Link to heading
Map over array to extract one field:
curl -s 'https://api.example.com/users' | jq '.[].email'
Get array length:
curl -s 'https://api.example.com/items' | jq '. | length'
Filter and map together:
curl -s 'https://api.example.com/items' | jq '[.[] | select(.active == true) | .name]'
Get keys of an object:
curl -s 'https://api.example.com/data' | jq 'keys'
Check if field exists:
curl -s 'https://api.example.com/data' | jq 'has("field_name")'
Sort by field:
curl -s 'https://api.example.com/items' | jq 'sort_by(.created_at)'
The jq syntax feels cryptic at first, but after debugging a few APIs you start to memorise the common patterns. I still look up the more complex transformations though.
My debugging workflow Link to heading
When I’m investigating an API issue, here’s what I usually do:
First request without jq to see if it’s even working:
curl -v 'https://api.example.com/data'The
-vflag shows headers, status codes, etc. Useful for seeing 401s or redirects.Add
-sto suppress progress bar and pipe to jq for pretty output:curl -s 'https://api.example.com/data' | jqIf the response is huge, I’ll extract just what I need:
curl -s 'https://api.example.com/data' | jq '.results | .[0]'Sometimes I’ll save the response to a file to avoid hammering the API whilst I figure out the jq filter:
curl -s 'https://api.example.com/data' > response.json jq '.results | .[0]' response.jsonFor POST/PUT requests, I’ll test the payload separately first:
echo '{"name": "test"}' | jq # validates the JSON
The combination of curl -v for headers and jq for parsing has saved me hours of debugging time. Much faster than opening Postman or trying to read minified JSON in the terminal.