Online viewers
Five pages that open a data file in a browser tab and let you query it. No account, nothing installed, and the file never leaves the tab.
- Parquet Viewer —
.parquet - JSONL Viewer —
.jsonl,.ndjson - SQLite Viewer —
.db,.sqlite,.sqlite3 - MDB and ACCDB Viewer —
.mdb,.accdb(Microsoft Access) - pg_dump Viewer —
.sql,.sql.gz,.sql.zst,.sql.lz4,.tar(PostgreSQL dumps)
They behave the same way, so this one page is the reference for all of them. The dump viewer differs
in one respect worth knowing before you open a file: a dump is a script, so opening it runs it —
against a PostgreSQL 18 compiled to WebAssembly that lives in the tab and is discarded with it.
Custom-format dumps (pg_dump -Fc) do not open, because only pg_restore reads that archive and it
has no WebAssembly build; convert one with pg_restore -f dump.sql yourfile.dump first.
From Google Drive
An Access file stored in Google Drive opens without downloading it: install
MDB and ACCDB Viewer from the Google Workspace Marketplace,
then right-click the .mdb or .accdb file in Drive and choose Open with → MDB and ACCDB Viewer.
The browser downloads the file directly from Drive and reads it in the tab; it does not pass through
our servers, and nothing is written back to Drive.
In your editor
The same viewers install as editor extensions, one per format, from the VS Code Marketplace and from Open VSX — which is where Cursor, Windsurf and VSCodium install from. A file then opens in an editor tab, and the editor's agent chat can read it through the viewer's own read-only tools.
| Viewer | VS Code | Open VSX |
|---|---|---|
| Parquet | Marketplace | Open VSX |
| JSON Lines | Marketplace | Open VSX |
| SQLite | Marketplace | Open VSX |
| MDB and ACCDB | Marketplace | Open VSX |
| pg_dump | Marketplace | Open VSX |
The pg_dump extension opens .dump, .backup, .pgdump, .sql.gz, .sql.zst and .sql.lz4 files
by itself. A .sql file is usually a script being edited, so it is not taken over: right-click it and
choose Open in PostgreSQL Dump Viewer. The same goes for .tar and .tgz.
Open a file
- Go to the viewer for your format.
- Drag the file onto the page, or click Choose files.
- The rows appear straight away, and the SQL editor is one tab away.
Nothing is uploaded. The file is read inside the browser tab, so there is no server copy to worry about and closing the tab leaves nothing behind — which is what makes it safe to open a file you were sent rather than one you own.
You can look and query, but not change: the viewers run SELECT only. The file you opened is the
file you still have.
Opening several files at once
Every viewer but the dump viewer holds several files of its format open together; a dump is a whole database, so that viewer holds one, and choosing another replaces it. In the Parquet and JSONL viewers each file becomes a named view, so the SQL reads like SQL rather than like a path:
SELECT c.country, count(*) AS orders, round(sum(o.amount), 2) AS total
FROM orders o
JOIN customers c USING (customer_id)
GROUP BY 1
ORDER BY total DESC
Stacking files that should have been one file is the same idea with a set operation. BY NAME
matches columns by name instead of position, which is what saves you when the writer added a column
halfway through the quarter:
SELECT * FROM january
UNION ALL BY NAME
SELECT * FROM february
Where the view names come from
The name is derived from the filename, because a filename is usually not a SQL identifier:
- everything that is not a letter, a digit or
_becomes_; - a name that would start with a digit gets an
f_in front of it; - a second file whose name collides gets
_2, then_3.
So 2026 orders-final.parquet is queried as f_2026_orders_final. You never have to work this out —
the sidebar shows the name each file was given, and clicking a file writes the query for you.
Dropping the same file twice does not open it twice: the copy already open is selected instead. Two different files that happen to share a name both open, under names that differ.
Querying multiple SQLite databases
In the SQLite viewer, select all the databases you want in one go — in Choose files or by dropping them together. Choosing again replaces the set rather than adding to it. Each database is attached under a name taken from its filename, and the tree shows one branch per database. A table is reached by putting that name in front of it, so one query can compare two copies of the same database or join tables that live in different files:
SELECT a.customer_id, a.name, b.name AS name_in_archive
FROM "sales".customers a
JOIN "archive".customers b USING (customer_id)
WHERE a.name <> b.name
The name is built like a view name — the extension is dropped, and anything that is not a letter, a
digit or _ becomes _ — with two differences: letters outside the Latin alphabet are kept, and a
name that starts with a digit gets no prefix, so quote it ("2026_orders"). main and temp belong
to SQLite, which is why main.db is attached as main_2.
Clicking a table writes the qualified query for you. A table named without its database is looked up in the databases in the order they were opened, and the first match wins — so when two files have a table of the same name, name the database.
Querying several Access databases
In the MDB and ACCDB viewer each opened database becomes a schema named after its file, built like a view name, and its tables sit inside it. A table is always reached with its schema in front:
SELECT p.Name, sum(o.Quantity) AS units
FROM sales.Orders o
JOIN catalog.Products p USING (ProductID)
GROUP BY 1
Files are added to the open set, as in the Parquet and JSONL viewers. The SQL is DuckDB's, not Access
SQL: Access-only syntax such as IIf() or #2024-01-01# date literals does not run.
Access databases
The MDB and ACCDB viewer opens Access 97 through Access 2024 and Microsoft 365 files: .mdb from the Jet 3 and Jet 4
engines and .accdb from ACE. The tree lists each file, its tables with their row counts, and each
table's columns with the type Access gives them. Access system tables are hidden.
Every table is loaded with a matching type, so values keep their meaning:
| Access type | Loaded as |
|---|---|
| Currency, Number (Decimal) | exact DECIMAL |
| Date/Time | TIMESTAMP |
| Yes/No | BOOLEAN, shown as true and false |
| Replication ID (GUID) | UUID |
| Number (Byte, Integer, Long Integer), AutoNumber | integer types |
| Number (Single, Double) | FLOAT, DOUBLE |
| Short Text, Long Text, Hyperlink | VARCHAR — a Hyperlink keeps Access's text#address# form |
| OLE Object | BLOB, shown as described under Binary and media values |
| Multi-value field | a list of its own element type, so len() and unnest() work on it |
| Attachment | the list of file names in the column, with the files themselves in a table beside it |
Access stores a picture in an OLE Object behind a header of its own — the class name, "Bitmap Image" or "Paint.Picture", and then the image. The viewer looks behind that header, so Northwind's category pictures show as pictures rather than as binary.
An attachment field holds whole files, so the files get a table of their own next to the one they
belong to — Employees with an Attachments field also opens Employees_Attachments, one row per
file, with Row (the position of its row in Employees, counting from 1), FileName, FileType,
Size and FileData. FileData is a blob like any other: its kind is read from the bytes, images
get a thumbnail, and the download carries the right type. A field holding no files adds no table.
Besides the tables:
- Relationships defined in Access are drawn on the Diagram tab — see ER diagram.
- Saved queries are listed under the file with their SQL. They are shown, not run, because they are written in Access SQL.
- Linked tables are named above the grid as not included: their rows live in another database.
- Password-protected databases. An
.accdbencrypted in Access 2007 or later asks for its password in the page; a wrong one is refused and you can try again. The password is used in the tab and not stored. An Access 2000–2003 database password does not encrypt the file, so such an.mdbopens without asking.
PostgreSQL dumps
The pg_dump viewer opens plain dumps (pg_dump -Fp) — uncompressed, or compressed with gzip,
zstd or lz4, the last two being what pg_dump 16 and later write with -Z zstd and -Z lz4 — and
tar dumps (pg_dump -Ft). The format is read from the file's first bytes, not its name, so a
dump called .backup or .dump opens if it is one of these.
Opening a dump runs it. Every CREATE, COPY and function body is replayed into PostgreSQL 18,
compiled to WebAssembly, in the tab; the tree then shows the database the dump describes — one
branch per schema, tables and views with their row counts, a partitioned table once with its
partition count beside it rather than once per partition. That also makes the viewer the safe place
to open a dump you did not make. Restored as a superuser on a real server, a hostile dump can run
shell commands through COPY … TO PROGRAM; here the same SQL runs in a PostgreSQL with no network,
no file system and no shell, and is discarded with the tab.
- Extensions come from the dump. Its
CREATE EXTENSIONlines are read before PostgreSQL starts, and exactly those extensions are loaded — PostGIS, pgvector, pg_uuidv7 and PostgreSQL's contrib set. A dump that needs none downloads none, and only a PostGIS dump pays for PostGIS. - Tables are reachable without their schema. A dump empties
search_pathfor its own statements; the viewer puts the dump's schemas back on it,publiclast, soSELECT * FROM ordersworks. - Your dump stays as it was. The file is only read, never written, and the database built from it is gone when the tab closes.
- Memory. The engine is 32-bit WebAssembly with a 2 GB memory ceiling, and PostgreSQL itself takes about 650–750 MB of it; the database the dump builds has to fit in the rest. A multi-gigabyte dump needs a real server.
Tabs: browsing, querying and the diagram
The right-hand pane has a Data tab and a SQL tab, and they do not share state. The SQLite, Access and pg_dump viewers add a third, Diagram — see ER diagram.
- Data previews whatever the sidebar has selected — a file in the Parquet and JSONL viewers, a table or view in the SQLite, Access and pg_dump ones. Clicking in the tree brings this tab forward and shows the rows.
- SQL holds the editor and its result. Clicking a file never touches it, so a query you are part-way through writing cannot be destroyed by a click in the tree.
Switching tabs re-runs nothing; both grids keep their sort, column widths and scroll position.
Press Ctrl+Enter (⌘+Enter) in the editor to run the query.
ER diagram
The Diagram tab of the SQLite viewer draws the tables and views of every open database and the
foreign keys between them; in the Access viewer it draws the tables and the relationships defined in
Access; in the pg_dump viewer, the tables and views and the foreign keys PostgreSQL holds once the
dump is replayed, with a key declared on each partition drawn once, on the table they partition.
Nothing is parsed out of DDL: the relations are the ones the database itself reports —
PRAGMA foreign_key_list in SQLite, pg_constraint in PostgreSQL — so two tables that merely
share a column name are not joined by a line. When a declared relation reaches none of the tables, the tab says so above the
diagram.
- Relations. One line per foreign key, with N at the referencing column and 1 at the key it references. A table that references itself loops back to itself.
- Views have a dashed border. The lines from a view to what it reads stay hidden until you select the view or tick View links, because on a real schema they are most of the clutter.
- Several databases each get a frame of their own colour.
- Select a table and its relations stand out: the table and the ones it is joined to keep their colour, their joining columns are marked, the links run, and everything else fades. The table is selected in the sidebar tree too. Picking a table in the tree centres it on the diagram.
- Move around with the wheel or trackpad, and zoom with Ctrl+wheel or a pinch. The toolbar at the bottom fits the whole diagram, zooms, and lays it out again — undoing any tables you dragged.
The file information panel
Under the file tree, a panel describes whatever is selected. It changes with the selection rather than describing the workspace, because with several files open a single header would be describing only one of them.
| Viewer | What the panel shows |
|---|---|
| Parquet | Rows, row groups, compression codec, uncompressed size, and the writer that produced the file |
| JSON Lines | The per-line validation result: how many lines are valid data, and how many failed to parse |
| SQLite | Rows, indexes, page size, page count, unused pages, text encoding, user version, application id, the SQLite version that wrote it, and a PRAGMA integrity_check result |
| pg_dump | Rows, partitions (for a partitioned table), schemas, indexes, the extensions the dump loaded, and the PostgreSQL version that replayed it |
For Parquet, each column in the tree expands to the statistics the file carries for it — minimum,
maximum, null count and share, compressed size on disk and uncompressed size. Those numbers belong
to the file, which is why they appear under the file and not next to the result of a query: after a
GROUP BY the minimum of a source column describes the file, not the rows on screen.
Why JSON Lines needs its own viewer
JSON Lines is one JSON value per line, which is what makes it streamable and also what makes a single bad line break a whole-file parse. So validation is per line: you get the count of valid data lines, the count and position of the ones that failed, and column types inferred across the whole file rather than guessed from the first record — nested objects included, and keys a JSON viewer usually mangles, like ones with dots or spaces in them.
Binary and media values
This applies wherever the data actually carries bytes: BLOB columns in SQLite and Parquet,
OLE Object columns and attached files in Access, and bytea columns in a PostgreSQL dump. JSON Lines has no binary type, so the case does not arise there — a
base64 string in a JSONL file is text, and is shown as text.
A BLOB is not printed as bytes. The cell shows its size and what the bytes turn out to be, and
images small enough to be cheap get a thumbnail:
The kind is worked out from the value itself, not from a column name or a file extension, so it is right even when the database says nothing about what it stores:
| What is in the blob | What you get |
|---|---|
| PNG, JPEG, GIF, WebP, BMP, ICO, AVIF, SVG | the picture |
| MP4, MOV, WebM, Matroska | a player, with controls |
| MP3, WAV, Ogg, FLAC | a player, with controls |
| TIFF, HEIC | the name and size — no browser can display these, so download it instead |
| text | the text |
| anything else | a hex dump of the first kilobyte |
Right-click a cell for Preview value and Download value. The download carries the detected
media type, so a blob that is a PNG arrives as a .png file.
Two limits are deliberate, and both exist so that a large value cannot make the grid expensive:
- thumbnails only for images under 512 KB. A larger image shows its size and opens in full when you ask for the preview;
- nothing is decoded while rows render. The preview builds its object URL when you open it and releases it when you close it.
A blob of zero length reads BLOB · empty, which is not the same as NULL and is not shown as one.
Exporting the result
The export button writes the result, not the page of rows the grid happens to show: the first 10,000 rows free, the whole result with PRO. A result that fits in one page is exported whole either way. The button belongs to the tab you are on: on Data it exports the file you are previewing, on SQL the result of your query.
| Viewer | Formats |
|---|---|
| Parquet, JSON Lines, Access | CSV, JSON, Parquet — written by DuckDB itself, so types survive the round trip |
| SQLite, pg_dump | CSV and JSON |
Binary values are written as hex in CSV and JSON. To get the bytes themselves, use Download value on the cell.
Limits
- Read-only.
SELECTandWITH … SELECTonly — noINSERT,UPDATE,CREATEorCOPY. - A file has to exist already. The viewers open data; they do not generate or edit it.
- Reading is not capped. The grid asks the engine for a page of rows at a time, so a table of 200,000 rows is browsable to its last row. Sorting is done by the engine over the whole result; column filters are switched off while a result is paged, so filter in SQL instead.
- Export writes the first 10,000 rows, and the whole result with PRO. A result that fits in one page is exported whole either way.
- One format at a time. Several Parquet files together, several JSONL files together, several SQLite databases or several Access databases together — but not Parquet joined to JSONL, and not a file joined to a database of another format. One PostgreSQL dump at a time.
- pg_dump custom (
-Fc) and directory (-Fd) dumps do not open. Onlypg_restorereads the custom archive, and it has no WebAssembly build; a directory dump is a folder, which a file picker cannot hand over as one file. - Access forms, reports, macros and VBA modules are not shown, and saved queries are not run.
- Ten SQLite databases at once. That is SQLite's own limit on attached databases. Choose more and the first ten open; the viewer names the ones it left out.
- The browser's memory is the ceiling. There is no fixed file-size limit; what a tab can hold depends on the machine, the format and the query.
Querying across different sources is a DBConvert Streams feature rather than a browser one — see Federated queries.
When a file will not open
- Wrong page for the file. Each viewer checks the signature and says which of the pages the file belongs to, rather than failing vaguely. Opening a Parquet file in the JSONL viewer is a one-click correction.
- A JSONL file with malformed lines is reported with the count before anything is queried. Other files already open stay open.
- A UTF-16 SQLite database next to a UTF-8 one. SQLite requires every database on one connection to share a text encoding, so the viewer names the file that differs. Open it on its own.
- A custom-format dump (
pg_dump -Fc) is refused by name, with the command that converts it:pg_restore -f dump.sql yourfile.dump. - A dump that needs an extension nobody has built for WebAssembly — TimescaleDB, say — opens in part. Everything that did not depend on it is there, and Opened in part lists what was lost and why.
- A dump cut off before its end opens what was complete, and the same report says the file is cut short rather than quoting a syntax error.
- A SQLite database marked as WAL but without its
-walsidecar is still a valid, self-contained snapshot when its changes were checkpointed, so it is read as one. That affects only the private copy in the tab; your file is not modified.