SQLite Viewer / Playground
Open a .sqlite file, browse tables and run real SQL in your browser — SQLite compiled to WebAssembly, nothing uploaded.
Queries you run stay here for this visit only — nothing is stored.
Press ? for shortcuts · The engine is downloaded from this site once; your database file and SQL never leave the page.
Do it offline:$ sqlite3 app.sqlite "SELECT name FROM sqlite_master WHERE type='table';"
How to use it
- Open a .sqlite / .db file — or load the bundled sample database — and the schema tree fills with its tables, columns, indexes and row counts.
- The first open downloads the ≈322 KB engine once; the file's 100-byte header is checked before that, so a wrong file refuses without any download.
- Write SQL in the editor and press Run (⌘/Ctrl + Enter). Results render as a grid, 100 rows per page, with NULL and BLOB values badged.
- Click Browse on any table for an immediate SELECT *, and re-run anything from the session's query history.
- Changes run on an in-browser copy — your original file is untouched. Press Export to download the copy, edits included, as a .sqlite file.
Open a .sqlite or .db file and it becomes a live database in this tab: browse every table with computed row counts, then run real SQL against it — joins, PRAGMA introspection, EXPLAIN QUERY PLAN, even INSERT and UPDATE. The engine is SQLite itself, compiled to WebAssembly and running in a worker, so results and error messages match the sqlite3 in your terminal. The file is read on this device and never uploaded.
How it works
The engine is sql.js 1.14.2 — the SQLite C library, version 3.49.1, compiled to WebAssembly. It runs inside a Web Worker on this page: opening a file copies its bytes into the worker, where they become an in-memory database the real SQLite query planner executes against. That is why behavior matches your terminal — the same B-tree code, the same SQL dialect, the same error strings. Saving works the other way round: Export serializes the worker's database image back into a standard .sqlite file, so schema and data round-trip byte-faithfully through the download.
Before any engine bytes are fetched, the tool reads the file's first 100 bytes — the database header defined by the SQLite file-format specification. Offset 0 must carry the 16-byte magic "SQLite format 3\0"; offset 16 encodes the page size; offsets 18 and 19 mark a WAL-mode file; offset 56 names the text encoding; offset 60 is your PRAGMA user_version. A zip, a CSV or an encrypted container fails the magic check and is refused with a hexdump of its first 16 bytes — before the ≈322 KB download is ever worth paying for.
The schema tree is built the way SQLite documents it: a query over sqlite_master lists tables, views, indexes and triggers, then PRAGMA table_info names each table's columns with their declared types, NOT NULL flags and primary keys, PRAGMA foreign_key_list maps the references between tables, and PRAGMA index_list finds unique indexes. Row counts are genuine COUNT(*) results computed per table. Query results keep up to 10,000 rows, paged 100 at a time, and integers are fetched over sql.js's BigInt path so 64-bit values survive exactly.
Examples
SELECT ar.name, COUNT(*) AS albums, ROUND(SUM(al.price),2) AS total
FROM albums al JOIN artists ar ON ar.id = al.artist_id
GROUP BY ar.name ORDER BY albums DESC;name|albums|total
Holly Golightly|2|17.24
Mina|1|12.5A JOIN with GROUP BY against the sample database — the grid shows the aggregated columns exactly as SQLite computes them, REAL sums included.
SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;name
albums
artistsThe master catalog query — sqlite_master is a real table in every database file, and this one-liner is the fastest inventory of what a file contains.
PRAGMA table_info(albums);cid|name|type|notnull|dflt_value|pk
0|id|INTEGER|0||1
1|title|TEXT|1||0
2|artist_id|INTEGER|0||0
3|price|REAL|0||0Column introspection, one PRAGMA away: declared type, NOT NULL flag and primary-key position per column. The empty dflt_value cells are NULL — the grid badges them as NULL.
EXPLAIN QUERY PLAN SELECT title FROM albums WHERE artist_id = 1;id|parent|notused|detail
3|0|61|SEARCH albums USING INDEX idx_albums_artist (artist_id=?)The real query planner speaking: the WHERE clause is answered by the idx_albums_artist index as a SEARCH, not a full-table SCAN — the same plan sqlite3 prints in a terminal.
INSERT INTO artists VALUES (3,'Nina Simone');
SELECT id, name FROM artists ORDER BY id;id|name
1|Holly Golightly
2|Mina
3|Nina SimoneWrites work — on the in-browser copy. Statements run in order, the last result set is displayed, and Export then carries the new row out as a .sqlite download; the file you opened is untouched.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
The 100 MiB cap, and why it exists
Files cap at 104,857,600 bytes. The copy-open model holds the whole database image in the worker's WebAssembly memory, and a 32-bit wasm heap has to carry the image, the page cache and your result rows together — 100 MiB keeps honest headroom. Bigger databases belong to sqlite3 on your machine, which reads pages from disk instead.
WAL files: -wal and -shm sidecars are not merged
A database in WAL mode keeps recent writes in a separate -wal file. This tool reads only the main file you pick, so those unmerged writes are invisible here — the header's read/write version bytes flag such files and the page shows a WAL notice. Run PRAGMA wal_checkpoint against the database on your machine first to fold the log into the main file.
BLOB cells render as a size badge, not a byte dump
A BLOB column can hold megabytes per row, so the grid shows BLOB · size with the first 16 bytes as a hex preview instead of flooding the page. The bytes stay intact in the database — Export carries them out in full.
Integers past 2^53 arrive as exact digit strings
SQLite INTEGERs are 64-bit; a JavaScript number is exact only to 9007199254740992. A naive bridge would silently round 9007199254740993 down to that even neighbour — this tool fetches integers over the BigInt path and prints the exact digits as text, dotted-underlined in the grid.
Text cells trim at 2,048 characters — for display only
A cell longer than 2,048 characters is shown shortened with an ellipsis so one row cannot swallow the grid. The stored value is untouched: SUBSTR, LENGTH and Export all see the full text.
Common errors
no such table: missing- The classic first error in a foreign file: the table name is spelled differently than you expect. The schema tree and the sqlite_master query in the examples are the ground truth — SQLite names the missing table itself, and the banner repeats its words exactly.
near "SELEC": syntax error- SQLite's parser points at the first token it could not read. The message is rendered verbatim from the engine, so what you debug here is what sqlite3 would print in a terminal.
file is not a database- The engine's verdict when a file passes the 16-byte magic check but the pages behind it do not parse — most often an encrypted SQLCipher database or a truncated download. Encryption is not part of public SQLite, so such files cannot open here; decrypt them with your SQLCipher tooling first.
UNIQUE constraint failed: artists.id- Constraints are enforced for real, because the writes are real — inserting a duplicate primary key into the sample database fails exactly as it would anywhere else. The change that failed touched only the in-browser copy.
FAQ
Is my database file uploaded anywhere?
No. The engine — SQLite compiled to WebAssembly, ≈322 KB — is downloaded from this site once; your file is then read into a worker inside this tab and sent nowhere. Share links carry only the SQL text and the view choice: the database bytes cannot ride a link at all.
What is the file size limit?
104,857,600 bytes — 100 MiB. The whole database image lives in the worker's memory while you query it, and that cap keeps the 32-bit WebAssembly heap comfortable. For anything larger, sqlite3 on your machine reads pages from disk and has no such ceiling.
Can I edit data and save the result?
Yes — INSERT, UPDATE, DELETE, CREATE and DROP all run, against an in-browser copy of your file. The original on disk is never written. Press Export (or ⌘/Ctrl + S) to download the copy, changes included, as a standard .sqlite file that any SQLite tool opens.
Which SQLite version runs here?
sql.js 1.14.2, which embeds SQLite 3.49.1 — run SELECT sqlite_version(); in the editor and the engine answers for itself. Version-sensitive behavior like EXPLAIN QUERY PLAN wording follows that release.
Can I open WAL-mode or encrypted databases?
A WAL-mode file opens, but its -wal / -shm sidecars are not merged, so writes still sitting in the log are invisible — checkpoint on your machine first. Encrypted databases (SQLCipher and similar) are not part of public SQLite and fail with the engine's own words: file is not a database.
How many rows can a query return?
Up to 10,000 rows are kept per query and rendered 100 per page; past the cap the grid says so and the honest fix is WHERE or LIMIT. A query that runs past 20 seconds is stopped by terminating the worker, and the page tells you the in-tab copy was reset.
Keyboard shortcuts
- ⌘/Ctrl + Enter
- Run the SQL now.
- ⌘/Ctrl + S
- Export the database copy as a .sqlite file.
- ⌘/Ctrl + C
- Copy the results page when nothing is selected.
- ⌘/Ctrl + Shift + C
- Copy the results page even with a selection active.
- t
- Cycle the color theme.
- ? or ⌘/Ctrl + /
- Show the shortcut overlay.
- Esc
- Cancel a run, or dismiss a banner.