jq Playground

Run jq 1.7.1 filters in your browser with -r, -s, -n, --arg and JSON Lines. Output, stderr and exit codes match the jq CLI; error hints show the bad spot.

  • Runs in your browser
  • Your data never leaves your browser
  • Free · No Sign-Up
The filter runs 0.25 seconds after you stop typing; an empty filter runs as . (identity). Ctrl+Enter (⌘+Enter on a Mac) runs it at once. Paste a whole command line such as curl … | jq -r '.items[]' and the page offers to take its filter, options and variables. It also offers to remove shell quotes around a filter and to replace fullwidth punctuation and curly quotes outside strings. import, include and -f need files on disk and are not available.
Runs the filter now. Input over 2 MB does not run as you type, so press Run for it. After 1 second the button turns into Stop. A run is stopped after 10 seconds plus 1 second per MB of input; a filter such as repeat(1) never finishes on its own.
Each button is a jq command-line option; turn it on as you would pass it to jq. -r prints strings without quotes, -c prints each value on one line, -s reads every input value into one array, -n starts from null so that the filter reads the input with input or inputs, and -R reads the input as lines of text. Hold the pointer over a button to read what it does. Indent sets the indentation of JSON output (--indent n or --tab). Adds a variable that the filter reads as $name. --arg passes the value as a string; --argjson parses the value as JSON, so 10 is a number and {"a":1} is an object. A name has letters, digits and _ and does not start with a digit. The filter does not run while a name is invalid or used twice, or while an --argjson value is not valid JSON.
2 values
JSON, several JSON values one after another (JSON Lines, NDJSON), or plain text with -R. Open file reads a UTF-8 file of up to 200 MB; you can also drop a file on this panel. A file over 2 MB is not shown in the editor: you see its first 20,000 characters and jq reads the whole file. Input over 2 MB runs only when you press Run. Clear empties the input and the output and keeps the filter. The filter, the options, the variables (names and values) and an input of up to 40 KB that you type or paste are saved in this browser and come back when you return; opened files are not saved. Clear removes the saved input.
Output What jq writes to stdout, unchanged. When jq reports an error, its stderr text appears under the output and the exit code in the status line above the panels; Show in input and Show in filter select the position jq reports. The panel shows the first 1 MB and colours JSON up to 256 KB; Copy and Download always give the whole output. Download saves output.json, output.jsonl with -c, or output.txt with -r or -j.
"A-1001"
"A-1003"
Command line The same run as a shell command: save your input as input.json and paste the command into bash or zsh. The filter and the variable values are quoted for a POSIX shell. Copy link copies a link that holds the filter, the options and the variable names; the input and the variable values stay on this device. jq '.orders[] | select(.status == "paid") | .id' input.json

Engine: jq 1.7.1, the official C source compiled to WebAssembly (jq-web 0.6.2). It runs in a background worker in this tab; nothing is uploaded.

Examples, details and FAQ Worked examples, how it compares with other tools, and answers to common questions.

Example: open pull requests by one author

A GitHub REST API list response (shortened) in Input, -r on, and a variable who = octocat:

[{"number":42,"title":"Fix login redirect","draft":false,"user":{"login":"octocat"}},
 {"number":43,"title":"WIP: new parser","draft":true,"user":{"login":"hubot"}},
 {"number":44,"title":"Bump jq to 1.7.1","draft":false,"user":{"login":"octocat"}}]
.[] | select(.draft | not) | select(.user.login == $who) | "#\(.number)\t\(.title)"

Output (2 lines, tab-separated):

#42	Fix login redirect
#44	Bump jq to 1.7.1

The Command line box reads jq -r --arg who octocat '.[] | select(.draft | not) | …' input.json. If you call the API with GitHub CLI instead, note that gh api … --jq does not run jq: it uses gojq, a Go reimplementation, and prints top-level strings raw as if -r were on (go-gh pkg/jq). The gojq README lists the differences: it does not keep object key order, has no -S, -a or --seq, and keeps integer precision in arithmetic where jq does not.

Example: summarise JSON Lines logs

Access logs often have one JSON object per line. With -s (slurp) and -c:

{"ts":"2026-10-01T09:00:01Z","path":"/api/orders","status":200,"ms":42}
{"ts":"2026-10-01T09:00:02Z","path":"/api/orders","status":500,"ms":1203}
{"ts":"2026-10-01T09:00:02Z","path":"/health","status":200,"ms":3}
{"ts":"2026-10-01T09:00:03Z","path":"/api/orders","status":200,"ms":57}
group_by(.path) | map({path: .[0].path, requests: length,
  errors: map(select(.status >= 500)) | length, avg_ms: (map(.ms) | add / length)})
[{"path":"/api/orders","requests":3,"errors":1,"avg_ms":434},{"path":"/health","requests":1,"errors":0,"avg_ms":3}]

-s holds every line in memory. For large files, -n with reduce inputs as $r (…) reads one value at a time; the Options: —arg, -s, -n, -R group in Examples has both forms.

When jq stops with an error

jq prints the values it produced before the error, then the error on stderr, and exits with code 5. The page keeps both:

.items[] | .tags[] on {"items":[{"id":1,"tags":["a"]},{"id":2,"tags":null},{"id":3,"tags":["b","c"]}]} outputs "a", then jq: error (at input.json:1): Cannot iterate over null (null) and exit code 5. The hint below suggests .tags[]? or (.tags // [])[]. For a JSON syntax error, Show in input selects the token jq stopped at; jq reports the position in bytes, and the page converts it so that {"日本":1 x} selects the x. For a filter error, Show in filter selects the reported line.

The page also catches mistakes jq only reports as unexpected INVALID_CHARACTER: curly quotes from a word processor, fullwidth | or . from an input method, and a filter still wrapped in shell quotes.

Same result as your terminal

Each run is jq FLAGS FILTER input.json, where input.json holds the input plus a final newline. Our test suite runs 71 cases (options, variables, JSON Lines, syntax and runtime errors, halt_error, -e, --seq, --stream) through this page’s engine and through jq 1.7.1, and compares stdout, stderr and the exit code byte for byte. It also runs the 241 examples of the jq 1.7.1 manual; all match except the two that read $PAGER from the environment.

Which jq do you have? Run jq --version. Ubuntu 24.04 (jq 1.7.1-3ubuntu0.24.04), Debian 13 (1.7.1-6) and macOS 27 (/usr/bin/jq prints jq-1.7.1-apple) have 1.7.1. Homebrew has 1.8.2. jq 1.8.0 (NEWS) added trim, ltrim, rtrim, trimstr, toboolean, skip, add/1 and @urid, made ltrimstr error on non-strings and limit error on a negative count, and changed how -1 as $x | … binds. Large integers are kept as written, but arithmetic uses doubles in 1.7.1:

.order_id, .order_id + 0 on {"order_id": 9007199254740993} prints 9007199254740993 and then 9007199254740992.

How it compares (tested 2026-10-02)

We ran the same inputs on three other jq pages in Chromium:

  • play.jqlang.org (the jq project’s playground; jqplay.org now redirects there) runs jq 1.8 in the browser: trim works and no request carried our input. It shows output and error together, as here, and stopped repeat(1) with “Operation timed out” after about 30 seconds. Use it when you run jq 1.8.
  • jqkungfu.com runs jq.wasm locally. For .[] | .a on [{"a":1},2] it showed 1 without the error; 9007199254740993 came back as 9007199254740992; after a JSON syntax error the previous output stayed on screen.
  • jsonwiz.com/jq-online loads jq-wasm@0.3.1 from esm.sh, which answered 404, so every run showed “Failed to fetch dynamically imported module”.

Limits

  • No files besides the input: --slurpfile, --rawfile, -f, -L, import and include are not available; --args / --jsonargs are left out.
  • $ENV and env show the WebAssembly runtime’s fixed environment (HOME=/home/web_user), not yours. now and the local-time functions use your browser’s clock.
  • Inputs over 2 MB run only when you press Run; files over 2 MB are not shown in the editor. Output over 1 MB is cut in the panel (Copy and Download are complete).
  • A filter is stopped after 10 seconds plus 1 second per MB of input. A run that exhausts memory or recurses too deep restarts the engine.
  • Colour (-C) is ignored; output is not colourised.

Related tools: JSONPath Tester for path queries, JSON Formatter to pretty-print, JSONL Converter between JSON arrays and JSON Lines, JSON Diff to compare two outputs.

FAQ

Is this the real jq or a JavaScript copy?

It is jq 1.7.1 itself: the official C source compiled to WebAssembly by jq-web 0.6.2. The page runs it the way `jq FLAGS FILTER input.json` runs, and our test suite compares 71 filters byte for byte (output, error text, exit code) with the jq 1.7.1 command line, plus the 239 examples of the jq 1.7.1 manual that do not read environment variables.

Why jq 1.7.1 and not 1.8?

1.7.1 is the jq that Ubuntu 24.04, Debian 13 and macOS (/usr/bin/jq) ship, so a filter tested here behaves the same on those machines. jq 1.8 adds trim, ltrim, rtrim, trimstr, toboolean, skip, add/1 and @urid and changes a few behaviours; when a filter uses a 1.8 function, the page says so.

Is my JSON uploaded?

No. jq runs in a Web Worker in your tab. The only network requests are the jq engine files the first time you use the tool (jq.wasm, about 1 MB compressed). The share link carries the filter, the options and the variable names, never the input or the variable values.

Does the page remember what I typed?

Yes, in this browser only. The filter, the options, the variables (names and values) and an input of up to 40 KB that you type or paste are saved in this browser's local storage and come back when you open the page again. Opened files and larger inputs are not saved. Clear removes the saved input; the filter stays until you change it.

How big can the input be?

Files up to 200 MB. Inputs over 2 MB do not run on every keystroke; press Run. The output panel renders the first 1 MB and Copy / Download give the whole output. A filter that runs longer than 10 seconds (plus 1 second per MB of input) is stopped.

My filter works here but not in my shell. Why?

Usually quoting. Copy the command from the Command line box: it puts the filter in single quotes and escapes any single quote inside it, which is what bash and zsh need. PowerShell and cmd.exe quote differently. Also check `jq --version`: on jq 1.8 a few results differ.