SQL in the Browser
Drop a CSV, Parquet, JSON or Excel file below and query it with SQL in this tab. The engine is DuckDB compiled to WebAssembly, so joins, common table expressions and window functions work in the first query you run, with no mode to switch on and no extra download. Your file is read locally and never uploaded. A starter query is written from your own columns and run for you.
Bigger than 100 MB, or want charts and a 40-step pipeline on top of the query? Open the full editor
Real DuckDB, not a SQL-shaped subset
Most browser SQL tools are not running a database. They are running a parser somebody wrote by hand, one that recognizes SELECT columns FROM csv WHERE column = value ORDER BY column LIMIT n and stops there. That covers the first five minutes. It falls over the moment you want a join, a HAVING clause, a subquery, a window function, or any of the seventy or so date functions a real engine ships with. Some of those tools offer a "power mode" checkbox that downloads a proper engine on demand, which means the query you learned to write in the morning behaves differently in the afternoon depending on a setting you have forgotten you toggled.
This page has one engine and it is the real one. DuckDB is an analytical database in the same family as SQLite, and its WebAssembly build runs the same query planner, the same vectorized execution and the same SQL dialect as the desktop binary. There is no reduced mode, no fallback parser, and nothing to opt into. The engine downloads once, in the background, the moment you hand the page a file, and it is cached by your browser after that.
That has a practical consequence worth spelling out. A query you write here is a query you can paste into a DuckDB session on your laptop, into a dbt model that targets DuckDB, or into a colleague's terminal, and it will behave the same way. You are not learning a dialect that exists only on one website.
What that buys you in practice
ROW_NUMBER, LAG, LEAD, running totals, ranking inside a partition, moving averages over a date frame.WITH blocks so a five-stage transformation reads top to bottom instead of nesting six subqueries deep.USING and ON, between two files you dropped a second apart.A worked example, start to finish
Press Try with sample data above and the page loads sales-10k.csv, a 10,000-row export with the columns order_id, order_date, region, channel, units, amount and refunded. Before you touch anything, the page has already counted the distinct values in each text column, decided that channel is the most useful thing to group by, decided that units is a quantity rather than an identifier, and run this:
SELECT channel, SUM(units) AS total FROM sales_10k GROUP BY 1 ORDER BY total DESC LIMIT 10
Three rows come back, one per channel, and the badge above the editor says the query is a starter. Now suppose the real question is revenue per month, excluding refunds, with each month's share of the year. That is one edit away, and it is the sort of query the hand-rolled parsers cannot express at all:
WITH monthly AS (
SELECT
date_trunc('month', order_date) AS month,
SUM(amount) AS revenue
FROM sales_10k
WHERE NOT refunded
GROUP BY 1
)
SELECT
strftime(month, '%Y-%m') AS month,
ROUND(revenue, 2) AS revenue,
ROUND(100 * revenue / SUM(revenue) OVER (), 1) AS pct_of_year
FROM monthly
ORDER BY month
Press Ctrl or Cmd plus Enter. Twelve rows come back with the elapsed time beside the row count, usually in single-digit milliseconds once the engine is warm. Click any column header to sort what is on screen without rewriting the query. Then take it somewhere: Download CSV, Download .xlsx for someone who lives in Excel, Copy as Markdown table to paste straight into a pull request or a ticket, or Send to the full editor to chart it.
For a join, press Add a file to join and drop a second file. Say it is a small table of regional targets. Both files become named tables, the second one also answers to the short alias t2, and the page notices that both carry a region column and offers the join as a starting point rather than running it silently. Joining on the wrong pair of columns produces a plausible and completely wrong number, which is worth one click of consent.
The editor, and what happens around it
The query box highlights as you type. Keywords, function calls, string literals, numbers and comments each get their own color, and strings and comments also change slant so the structure survives for a reader who does not separate red from green. Under the hood it is still an ordinary textarea with a painted layer behind it, which means your browser's undo stack, text selection, spell check and mobile keyboard all behave exactly as they do everywhere else.
Press Ctrl or Cmd plus Space, or just type two characters, and a completion list appears. Your own column names come first, then the table names and their short aliases, then DuckDB keywords and functions. Type t2. and the list narrows to that one table's columns. A column whose name has a space in it is inserted already quoted, so you never have to remember which of your headers need double quotes.
Every query you run is remembered, per file, up to the last fifty. The list is keyed on the file's name and its size, so the same export opened again picks up where you left off, while a bigger version of the same report starts a clean list instead of suggesting queries whose columns have moved. Anything worth keeping longer gets a name through ★ Save query, and named queries are global: one saved here is waiting for you in the SQL step inside the full editor, and on the other SQL pages on this site.
Results are capped at 2,000 rows on screen because a browser table with a hundred thousand rows in it helps nobody, but the downloads carry everything the query produced. The row count above the grid always tells you the true total, and says so plainly when what you are looking at is a slice of it.
What the page will and will not run
The workbench is read-only by construction, and the check happens in the page before anything reaches the engine. A query has to begin with SELECT, WITH, DuckDB's FROM-first shorthand, DESCRIBE, SUMMARIZE, EXPLAIN, VALUES, PIVOT or UNPIVOT. Only one statement runs at a time, so a stray semicolon cannot smuggle a second one in behind it.
INSERT, UPDATE, DELETE, DROP, TRUNCATE, ALTER, COPY, EXPORT, IMPORT, ATTACH, DETACH, INSTALL and LOAD are all refused. The last four matter most: they are how a DuckDB session reaches the network or the file system, and a page that reads your local files has no business doing either. Comments are stripped before the check, so a keyword sitting inside -- notes does not trip it, and a keyword inside a string literal is left alone.
Read-only table functions are allowed on the files you loaded. read_csv_auto, read_parquet and read_json_auto all work, which is useful when you want to override how a file was sniffed. The full allowed surface, and the same rules as they apply inside the app, are written up in the DuckDB SQL reference.
Frequently asked questions
Is this real SQL, or a subset of it?
It is DuckDB, compiled to WebAssembly and running inside the page. Not a hand-written parser that understands SELECT, WHERE and ORDER BY and gives up on the rest. Joins across files, common table expressions, window functions, GROUPING SETS, QUALIFY, list and struct types, regular expression functions and the full date and time library all work from the first query you run, with no checkbox to tick and no second engine to download.
Does my file get uploaded anywhere?
No. This page has no upload endpoint. The bytes are read by JavaScript in your own tab, registered with the in-page database as a virtual file, and queried there. Nothing is posted to a server, nothing is stored between visits unless you save a query by name, and you can confirm all of it by opening your browser's network panel while you work.
What is the largest file this page can query?
100 MB. Past that the page warns you and offers to hand the same file to the full editor at /app, which streams it instead of holding all of it in memory at once and copes with files up to a gigabyte. Within 100 MB there is no row limit, no watermark, no daily allowance and no sign-up.
Which file formats can I query?
CSV, TSV, plain-text delimited files, JSON, JSON Lines and NDJSON, Parquet, and Excel workbooks in .xlsx or .xls. CSV and Parquet are read by DuckDB directly. A workbook's first sheet is flattened to CSV in the page before it is registered, so a spreadsheet becomes queryable without any conversion step of your own.
Can I join two files?
Yes. Press Add a file to join, drop the second one, and both are registered as tables you can name in a single query. When the two files share a column name the page writes the join for you as a starting point. There is no two-file ceiling in the engine itself, and the full editor at /app joins across as many loaded tables as you have.
What is the starter query, and can I get rid of it?
When your file lands, the page reads its column types, counts the distinct values in the text columns, picks the lowest-cardinality category and the most quantity-like number, and writes a grouped total over the two. It runs immediately so you see an answer rather than an empty box. It is badged as a starter query, and typing anything at all clears the badge. Nothing about it is sticky.
Can I write to my file, or create tables?
No. The page accepts read-only statements: SELECT, WITH, DuckDB's FROM-first shorthand, DESCRIBE, SUMMARIZE and EXPLAIN. INSERT, UPDATE, DELETE, DROP, ALTER, COPY, ATTACH, INSTALL and LOAD are all refused before anything reaches the engine, and only one statement runs at a time. Read-only table functions such as read_csv_auto and read_parquet are allowed on the files you loaded.
Where do my saved queries live?
In IndexedDB, in your own browser, in a database that belongs to this feature alone. History is kept per file, the last fifty queries of it, keyed on the file's name and size so re-running last month's report against a bigger export starts a clean list. Saved queries are global, so a snippet written here shows up in the app's SQL step too. Clearing site data removes both.
Related tools and guides
Query your own file
Free, no account, no upload, no daily allowance. Real DuckDB from the first query.
Back to the workbench