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:

  1. First request without jq to see if it’s even working:

    curl -v 'https://api.example.com/data'
    

    The -v flag shows headers, status codes, etc. Useful for seeing 401s or redirects.

  2. Add -s to suppress progress bar and pipe to jq for pretty output:

    curl -s 'https://api.example.com/data' | jq
    
  3. If the response is huge, I’ll extract just what I need:

    curl -s 'https://api.example.com/data' | jq '.results | .[0]'
    
  4. 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.json
    
  5. For 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.

  • jq manual - comprehensive reference for all jq features
  • jq play - interactive jq playground for testing filters