Skip to content
Tools

JSONPath Tester

Write and test JSONPath expressions against JSON data with instant matching, result preview and path visualization. Everything runs locally in your browser.

Visible pane

Return the whole document.

Result view

0 results found

Paste JSON and enter a JSONPath expression to begin testing.

Waiting for JSON

Everything happens locally in your browser. Your JSON is never uploaded.

What is JSONPath?

JSONPath is a query language for JSON. Rather than writing code that walks a document key by key, you write one expression describing the nodes you want, and the engine finds them.

One expression instead of a loop
$.users[*].email // instead ofdata.users.map(user => user.email)

It was introduced by Stefan Gössner in 2007 as a JSON counterpart to XPath, and for most of its life it was an article rather than a specification — which is why implementations disagree in the corners, particularly around filters. RFC 9535 standardised it in 2024. This tester follows the behaviour the widely used implementations agree on, so expressions copied from documentation work here.

It shows up in more places than most people realise: API testing tools, CI pipelines, webhook routers, log processors and low-code platforms all accept a JSONPath as the way to point at a value inside a payload.

How JSONPath works

An expression is a series of steps. Evaluation starts with one node — the root — and each step transforms the current set of nodes into a new one. That is the whole model, and it explains most of the surprises.

Four steps, four transformations
$.store.book[*].title $          → the whole document          (1 node).store     → the store object            (1 node).book      → the array of books          (1 node)[*]        → each book                   (4 nodes).title     → the title of each book      (4 nodes)

Because each step works on a set, a step that does not apply simply produces nothing rather than an error. Asking for .title on a node that has no title drops that node, which is why a query can return fewer results than you expected without ever failing.

This tester shows that reasoning back to you in words underneath the expression. If the explanation does not describe what you meant, the query is wrong even if it returns something.

JSONPath syntax

Almost every expression you will write is built from these pieces.

$
The root of the document. Every expression starts here.
@
The node currently being tested. Only meaningful inside a filter.
.name
A property, by name. The everyday step.
['name']
The same thing, for keys with a space, dot or hyphen in them.
*
Every child. $.users[*] is every item; $.user.* is every property.
..
Recursive descent. $..price finds every price at any depth.
[0] [-1]
An array index. Negative counts back from the end.
[1:5] [::2]
A slice: half-open, with an optional step.
[0,2]
A union — several indexes or names at once.
[?(…)]
A filter. Keeps the items whose condition is true.
[(…)]
A script expression, evaluated as arithmetic and used as an index.
.length
The length of an array or a string.

Two of these are worth dwelling on. Recursive descent (..) searches the entire subtree, which makes it enormously useful and the slowest thing in the language — it visits every node. And a filter tests each child of the current node, with @ bound to the child being tested, which is why $.users[?(@.age > 18)] reads as “the users where age is over 18”.

JSONPath examples

Every one of these is in the tester’s library — one click loads it against the sample document so you can see what it returns.

$.users[*].email

Every user's email. The single most common shape of query there is.

$..author

Every author anywhere in the document, however deep.

$.store.book[0]

The first book. Indexes start at zero.

$.store.book[-1]

The last book, without needing to know how many there are.

$.store.book[0:3]

The first three books — half-open, so index 3 is excluded.

$.users[?(@.age >= 18)]

Only the adults. Items with no age are skipped rather than erroring.

$.book[?(@.price < 10 && @.category == 'fiction')]

Two conditions, combined.

$.users[?(@.email)]

Only the users that have an email at all.

$.orders[*].items[*].sku

Reaching through two levels of array.

$.store.book[(@.length-1)]

A script expression: the last item, computed.

$['first-name']

Bracket notation, needed because of the hyphen.

$..*

Every node in the document. Useful for seeing the whole shape.

JSONPath vs XPath

JSONPath was designed as XPath for JSON, and the resemblance is deliberate. If you know one, most of the other is guessable — and when the document in front of you is XML rather than JSON, the XML formatter gives it the same collapsible tree to explore.

IdeaXPathJSONPath
Root/$
Child/store/book$.store.book
Every child/store/*$.store.*
Any depth//author$..author
Index/book[1]$.book[0]
Filter/book[price<10]$.book[?(@.price < 10)]
Current node.@

The differences that actually matter:

  • XPath indexes from one, JSONPath from zero. This catches everybody at least once.
  • XPath is a W3C standard with a full function library. JSONPath was an article until RFC 9535 in 2024, and has no agreed function set — which is why .length works in some implementations and not others.
  • XPath can walk upwards. It has parent and sibling axes; JSONPath only ever goes down.
  • XML distinguishes attributes from elements. JSON has only keys and values, so JSONPath needs no equivalent of @attr — which is exactly why @ was free to mean the current node instead.

Common use cases

API testing

Assert that a response contains what it should. Most API testing tools accept a JSONPath as the thing to check, so getting the expression right here saves a failing build later.

REST APIs

Pull one field out of a deeply nested response without writing a chain of optional accesses in code.

Data extraction

Lift every price, id or email out of a document in one expression, whatever shape it arrived in.

Automation

CI pipelines, webhooks and low-code tools all take JSONPath as a way to route on a value inside a payload.

Configuration files

Find every occurrence of a setting across a large config, including the ones nested three levels down.

JSON processing

Work out the right expression here, then paste it into jq, a library, or whatever runs it in production.

Software development

Explore an unfamiliar response quickly: $..* shows the whole shape, then narrow from there.

JSONPath best practices

  • Build the expression one step at a time. Start with $, add a step, check the count, add the next. Debugging a five-step expression that returns nothing is much harder than never writing one. If you already know the one value you are after, the JSON viewer will hand you its path to start from.
  • Prefer an explicit path to recursive descent. $.store.book[*].price visits four nodes; $..price visits every node in the document and will also find prices you did not mean.
  • Remember that a missing value fails a comparison quietly. [?(@.price < 10)] skips items with no price rather than treating them as zero. That is usually what you want — but check, because it is also how a filter silently returns less than you expected.
  • Quote keys that are not plain identifiers. Anything with a space, a dot or a hyphen needs ['like-this']. Inside a filter a hyphen would otherwise read as subtraction.
  • Do not rely on result order for unions. [2,0] returns index 2 then index 0 here, but implementations differ. Sort afterwards if the order matters.
  • Test against a real response, not a trimmed one. Optional fields, empty arrays and nulls are exactly what breaks an expression in production, and a tidied-up example will not have them. Run the raw payload through the JSON formatter if it is unreadable, but do not delete anything from it.
  • Read the explanation before trusting the result. A query that returns four things is not necessarily returning the right four things.

Frequently asked questions

What is JSONPath?

A query language for JSON, in the same way XPath is a query language for XML. Instead of writing code to walk a document, you write one expression that describes the nodes you want — $.users[*].email returns the email of every user — and the engine finds them.

Is this JSONPath Tester free?

Yes. Live evaluation, all three result views, the expression library, search, download and copy are free, with no account and no limit on how many queries you run.

Is my JSON uploaded anywhere?

No. The document is parsed and queried by JavaScript running in your browser. Nothing is sent to a server, nothing is stored and nothing is logged. You can disconnect after the page loads and it keeps working — which matters, because the documents people test against are usually real API responses.

Can I test filters?

Yes. Filters are written [?(…)] with @ standing for the item being tested — $.book[?(@.price < 10)] keeps the cheap ones. You can compare with ==, !=, <, <=, > and >=, combine conditions with && and ||, group them with parentheses, negate with !, and test for existence by naming a property on its own.

Does it evaluate filters with eval?

No, and that is deliberate. The widely used JSONPath libraries hand filter and script expressions to eval or static-eval, which is how one of them ended up with a critical remote-code-execution advisory. This engine parses expressions into a small tree and walks it, so a filter can compare and calculate but can never execute code. Attempts to reach the constructor or assign to globals are rejected at parse time.

Does it support recursive search?

Yes. $..price finds every price anywhere in the document, at any depth, and $..* returns every node. This is the fastest way to find where something lives when you do not already know the shape of the data.

Can I search nested arrays?

Yes. Wildcards chain, so $.orders[*].items[*].sku reaches into every item of every order. Recursive descent does the same job without knowing the structure: $..sku finds them wherever they are.

What syntax is supported?

The root $, the current node @ inside filters, dot and bracket notation, wildcards, recursive descent, array indexes including negative ones, slices with an optional step, unions of indexes or names, filters, script expressions such as [(@.length-1)], and .length on arrays and strings.

Why does my expression return nothing?

Usually because a key is spelled differently from what you expect, or because a step is applied to the wrong type — an index against an object, or a property against an array. The explanation under the expression describes what the query actually does in words, which is generally enough to spot the mismatch. Switching to the Tree view also shows which nodes were reached.

What is the difference between .. and .*?

$.* returns the direct children of the current node, one level down. $..* returns every descendant at every depth. Similarly $.price only finds a price at the top level, while $..price finds one anywhere.

Can I copy matched values?

Yes. The copy button in the toolbar puts every matched value on the clipboard as a JSON array, and each row of the results table has its own copy button for a single value. The JSON path of any match can be copied from the table too.

Can I download results?

Yes. The download button saves the matched values as a .json file. Combined with the copy button, that covers both feeding the result into another tool and pasting it into a ticket.

How large a document can it query?

Up to about 20 MB. Parsing runs in a background worker so typing stays responsive, evaluation is a single iterative walk with no recursion, and the tree and table views only render the rows currently on screen. Queries that would touch too much of the document stop and say so rather than freezing the tab.

Are indexes zero-based?

Yes. [0] is the first item and [-1] is the last, counting backwards from the end. Slices are half-open in the Python sense: [0:2] returns the first two items, not three.

Does it follow a standard?

JSONPath began as a 2007 article by Stefan Gössner rather than as a specification, so implementations differ in the corners — particularly around filters and unions. RFC 9535 standardised it in 2024. This engine follows the common behaviour that the widely used implementations agree on, which is what makes expressions copied from documentation work here.

Are there keyboard shortcuts?

Ctrl/Cmd+Enter runs the query immediately, Ctrl/Cmd+Shift+C copies the results, Ctrl/Cmd+Shift+D downloads them, Ctrl/Cmd+Shift+L loads another sample and Ctrl/Cmd+Shift+Delete clears everything. Ctrl/Cmd+F opens the search, and Escape closes it.

Popular tools

↑ ↓NavigateOpenEscClose