Private PDF/JSON tools that run directly in your browser

JSON Query Playground

Paste JSON, write a real SQL SELECT query, get rows back - WHERE, GROUP BY, JOIN, aggregates, all of it. Nested JSON works too, without reshaping it first.

Don't want to send your data to a server at all? Use the browser-only version →

⚠️ Unlike TinyPDF's other tools, this one is server-backed. Your JSON and query run on the server (real SQL execution can't happen in-browser). Each request builds a throwaway database and discards it immediately after - nothing is stored - but don't paste anything genuinely sensitive here.

Load an example to see how it works

Quick test: look at the JSON you pasted above - is it already the list you want to query (it starts with [)? Then leave this blank. Is that list buried inside other keys instead - like {"order": {"items": [...]}}? Then type the path to it here, e.g. order.items.

Not sure where to start? Pick the closest example above, then edit the query and column names to match your own data.

Reference: root paths, limits & safety
When to leave root blank
Your pasted JSON is already the table: either a bare array of objects (becomes table data), or an object whose values are each arrays (one table per key). No path-finding needed.
When to set root
The list you want is nested inside other keys rather than being what you pasted at the top level - e.g. you have the whole order, but only want to query order.items. A dotted path (root: "order.items") reaches it without you having to cut it out yourself.
root as an object
{"items":"order.items","customer":"order.customer"} - same idea, but pulling more than one nested location out as separate tables so you can JOIN them.
Nested arrays inside a row
A value that's itself an array or object (like each order's own items) is kept as JSON text per row - reach into it with json_extract() or unnest it with json_each().
Limits
Read-only SELECT/WITH only; capped rows in and out; a query timeout.

Using this from your own code

Everything above runs through the browser form. There's also a plain HTTP API for calling this from a script or backend - same query engine, same safety rules, just authenticated with a key instead of the page's captcha. It's new, so the free daily allowance may change as we see how it gets used.

API docs

  1. Get a key using the card on the right: sign in with Google, then click Generate API key. It's shown once, so copy it immediately.
  2. Save it as an environment variable, not in your source code:
    TINYPDF_JSON_QUERY_API_KEY=tpk_your_key_here

    Only call this from your own server/backend code - never from browser-side JavaScript, where anyone viewing page source could copy your key.

  3. POST to /api/v1/json-query with your key in an X-Api-Key header. Body shape is identical to the form above (data, optional root, query) - no recaptcha_token needed here:
    curl -X POST https://tinypdf.in/api/v1/json-query \
      -H "X-Api-Key: tpk_your_key_here" \
      -H "Content-Type: application/json" \
      -d '{
        "data": {"order": {"items": [{"sku":"A1","qty":2,"price":499}]}},
        "root": "order.items",
        "query": "SELECT SUM(qty * price) AS total_paid FROM data"
      }'
  4. Response on success is the same shape you see in the playground above:
    {"columns": ["total_paid"], "rows": [{"total_paid": 998}], "row_count": 1, "truncated": false}
    On any error (bad SQL, bad root path, write attempt, timeout) you get {"error": {"message": "..."}} with the matching HTTP status - the exact same error text and root-path nudges as the browser form, since it's the same code underneath.

Free tier: 5 calls/day per key. Once you've used your 5 for the day, further calls return a 429 with {"error":{"code":"api_key_limit_reached"}} until it resets the next day. Paid plans for higher volume are coming - this is a playground for now while we see how it gets used.