SQLite file viewer
Data conversion
Loading
Loading tool
The tool is loaded only when you open it.
All processing for this tool happens in your browser. Your input is not sent to a server.
About this tool
Inspect a small standalone SQLite 3 database in your browser without uploading its contents or changing the original file. Open a local .sqlite, .sqlite3 or .db file, review stored table, index, view and trigger definitions, and browse rows from supported ordinary tables. The interface generates quoted SELECT queries with LIMIT/OFFSET and NOT INDEXED rather than accepting arbitrary SQL. Actual storage-class labels keep integers, real numbers, text, binary bytes and null distinct. Export a selected inclusive row range as typed CSV or a JSON envelope. The pinned sql.js engine and WASM are bundled as same-origin assets and start only when you open a database. Data and query results are not persisted. For queries over CSV/JSON sources, use the separate local SQL workbench.
Common uses
- Check the columns, declared types, defaults, primary-key positions and index metadata of an application’s exported database before deciding which ordinary table contains the records you need.
- Inspect a bounded sample of local database rows while preserving exact integer identifiers, Unicode, nulls and binary data instead of allowing spreadsheet software to infer their types.
- Extract up to 1,000 adjacent rows for a review or migration investigation, keeping all columns and explicit per-cell types while leaving the source file unchanged.
How to use it
- 1.Export a consistent standalone, unencrypted SQLite database from its source application. Select the file and Open database, or use the synthetic example. The filename extension is only a picker hint; the header, schema and limits are checked. WAL-mode files and sidecars are not supported. A readable schema is not a complete database-integrity certificate.
- 2.Select a schema object to inspect its stored CREATE definition. Ordinary tables show columns and index metadata. Browse a supported table to generate the bounded SELECT, then use Previous, Next or Go to page. Views, internal objects and generated-column tables are schema-only. If any virtual table is present, the entire database is schema-only and no table rows are read.
- 3.Choose a 1-based inclusive start and end row, with at most 1,000 rows in SQLite scan order, then download CSV or JSON. Empty tables use 0–0. Exports include all table columns and complete values, independently of the displayed page. Keep CSV header protection enabled. Clear session, cancellation or leaving the tool releases the in-memory session; saved downloads remain on your device.
Executable examples from synthetic SQLite files
Distinguish NULL, empty text and empty bytes
{
"file": "example.sqlite",
"table": "records",
"format": "json",
"start": 1,
"end": 2,
"safe": true,
"excerptColumns": [
"id",
"note",
"payload"
]
}{
"columnsExcerpt": [
"id",
"note",
"payload"
],
"rowsExcerpt": [
[
{
"type": "integer",
"value": "1"
},
{
"type": "null",
"value": null
},
{
"type": "blob",
"value": "00FF"
}
],
[
{
"type": "integer",
"value": "2"
},
{
"type": "text",
"value": ""
},
{
"type": "blob",
"value": ""
}
]
]
}The selected columns of the built-in example retain their storage classes. The first record has NULL and a two-byte BLOB; the second has empty TEXT and empty BLOB. Every INTEGER, including 1 and 2, is an exact decimal string. A real export contains all columns; excerptColumns only shortens this documentation.
Read UTF-16 text without dropping Unicode or NUL
{
"file": "utf16le.sqlite",
"table": "words",
"format": "json",
"start": 1,
"end": 3,
"safe": true,
"excerptColumns": [
"value"
]
}{
"columnsExcerpt": [
"value"
],
"rowsExcerpt": [
[
{
"type": "text",
"value": "猫😀"
}
],
[
{
"type": "text",
"value": "é"
}
],
[
{
"type": "text",
"value": "a\u0000b"
}
]
]
}SQLite decodes the UTF-16 LE database. The JSON excerpt retains the cat character, emoji, accented character and embedded NUL between a and b. The escape in JSON is data, not a string terminator. Some control characters may not be visible in the preview.
Keep CSV data typed, including formula-like text
{
"file": "example.sqlite",
"table": "records",
"format": "csv",
"start": 3,
"end": 3,
"safe": true,
"excerptColumns": [
"code",
"name",
"note"
]
}{
"csvRecordsExcerpt": [
[
"code",
"name",
"note"
],
[
"T:003",
"T:猫😀",
"T:=SUM(1,2)"
]
]
}These are records after CSV parsing, not the literal quoted CSV file. The leading-zero code remains T:003 and the formula-like text remains T:=SUM(1,2). The tag is always present; safe mode protects risky headers, without changing the text payload. Removing tags later requires a new spreadsheet-risk review.
Export an empty table with its columns
{
"file": "example.sqlite",
"table": "empty_table",
"format": "json",
"start": 0,
"end": 0,
"safe": true,
"excerptColumns": [
"id",
"value"
]
}{
"columnsExcerpt": [
"id",
"value"
],
"rowsExcerpt": []
}The only valid range of a zero-row table is start 0 / end 0. JSON still records its ordered column names, with an empty rows array; CSV would contain only headers. Empty-table support does not manufacture a data row.
Inspect actual types in a STRICT table
{
"file": "schema-edge.sqlite",
"table": "strict_values",
"format": "json",
"start": 1,
"end": 3,
"safe": true,
"excerptColumns": [
"value"
]
}{
"columnsExcerpt": [
"value"
],
"rowsExcerpt": [
[
{
"type": "text",
"value": "001"
}
],
[
{
"type": "real",
"value": 1.5
}
],
[
{
"type": "blob",
"value": "00FF"
}
]
]
}The strict_values fixture includes a supported STRICT table with an ANY column. Its values have TEXT, REAL and BLOB storage classes. The viewer reports each cell’s actual type instead of inferring all values from the column declaration.
Browse an ordinary WITHOUT ROWID table
{
"file": "schema-edge.sqlite",
"table": "without rowid",
"format": "json",
"start": 1,
"end": 2,
"safe": true,
"excerptColumns": [
"a",
"b"
]
}{
"columnsExcerpt": [
"a",
"b"
],
"rowsExcerpt": [
[
{
"type": "text",
"value": "x"
},
{
"type": "integer",
"value": "1"
}
],
[
{
"type": "text",
"value": "x"
},
{
"type": "integer",
"value": "2"
}
]
]
}This fixture uses an ordinary WITHOUT ROWID table with a composite primary key. Its quoted name contains a space. The generated SELECT reads both rows and keeps integers exact without assuming that every table has a rowid column. The shown scan order belongs to this immutable fixture.
Keep a generated-column table schema-only
{
"file": "schema-edge.sqlite",
"table": "generated"
}{
"error": "unsupported"
}The generated table is listed with columns and its stored definition, but browsing fails with unsupported. No generated expression is evaluated to provide a preview. This is a supported-profile limit, not evidence of corrupt data.
Do not initialize virtual-table extensions
{
"file": "virtual-fts5.sqlite",
"table": "docs"
}{
"error": "unsupported"
}The FTS5 virtual table remains visible as schema metadata but cannot be selected. The presence of any virtual table makes all tables in this database schema-only, including ordinary-looking extension shadow tables.
Refuse WAL-mode input instead of omitting commits
{
"file": "wal.sqlite"
}{
"error": "wal"
}The WAL-marked file fails at the header check with wal. The viewer does not load sidecars or guess whether they contain newer committed data. Export a consistent standalone copy from the source application.
Reject a truncated database file
{
"file": "truncated.sqlite"
}{
"error": "format"
}The declared page count and actual file length no longer agree, so this fixture fails with format. Nothing is returned as a partial valid database. Other corruption may only be discovered when the affected page is read.
Common SQLite inspection mistakes
- Opening a live application’s main file while ignoring its WAL or recovery journal, rather than exporting a consistent standalone copy.
- Assuming a readable schema or one successful page proves that every database page is intact.
- Interpreting a schema-only object as an empty table, or expecting a virtual-table extension to be loaded.
- Treating a declared column type or NOT NULL flag as a complete description of all actual storage classes and constraints.
- Reading 100,000+ as an exact count or assuming that row positions are sorted by a visible ID.
- Assuming an export contains only the first 12 displayed columns or the current preview page.
- Removing CSV type tags without decoding them, losing the null/text/blob distinction or reintroducing spreadsheet risks.
- Expecting an old result or pending download to survive replacing the file, cancellation, timeout or a language change.
Limits and notes
- The input profile is one standalone, unencrypted SQLite 3 database of at most 16 MiB, with a consistent supported header, zero reserved page bytes, UTF-8 or UTF-16 LE/BE text encoding, at most 200 schema objects and 128 columns per ordinary table. Names are limited to 1,024 UTF-8 bytes, a stored SQL definition or default/type text to 16 KiB, and the complete schema summary to 512 KiB. WAL-mode main files, WAL/SHM sidecars, SQL dump text, remote URLs, encryption and extension-specific file formats are not accepted. Export a consistent copy from the source application instead of copying a live database alone.
- Only ordinary supported tables are browsable. Views, triggers, internal SQLite objects and tables with hidden/generated columns are display-only; their expressions are not executed for browsing. Any virtual table disables all row access for the whole database, including ordinary-looking extension shadow tables. Table and index metadata remain subject to the supported profile. The interface generates its own SELECT statements with quoted identifiers, LIMIT/OFFSET and NOT INDEXED on an in-memory copy with query_only enabled. There is no custom SQL editor, WHERE filter, join, ORDER BY, schema modification, extension loading, repair or database-file export.
- The table counter reads at most 100,001 rows and exposes only the first 100,000. A + marker is a lower-bound warning, not an exact full-table count. Preview pages contain 25 rows and the first 12 columns, with names shortened at 160 characters and cell values at 500. Row positions follow the immutable session’s SQLite scan order, not a portable sorted or insertion order. Each text or BLOB cell is limited to 256 KiB, while internal row materialization and each serialized export must fit 6 MiB. Successful exports contain the full values and every column in the chosen range, up to 1,000 rows. An operation fails on a limit rather than silently exporting a shortened value. Opening and sampling do not run a full integrity check; corruption in unread pages may remain undetected.
- Every INTEGER is an exact decimal string, including small values. REAL remains a number except +Infinity, -Infinity and -0, which use explicit strings; this does not make SQLite arithmetic exact. TEXT retains its content, including embedded NUL, and BLOB uses uppercase hexadecimal. NULL, empty TEXT, empty BLOB and numeric-looking TEXT have separate type tags. JSON uses ordered columns and row arrays of {type,value} cells, plus table and range metadata. It is an inspection format, not a database backup. Some control characters may not be visually apparent in a preview; inspect the JSON escapes when exact text matters.
- CSV uses UTF-8, comma separators and CRLF records. Every data value has a two-character tag: N: for NULL, I: for integer text, R: for real text, T: for text and B: for uppercase hexadecimal bytes. N:, T: and B: are distinct. Strip exactly one tag to obtain a non-null payload; literal text containing tags is preserved behind T:. Formula protection changes risky headers only, adding an apostrophe, and is on by default. Disabling it keeps all data tags but can expose header formulas; removing tags later can reintroduce formula and type-coercion risks. Each request has a 10-second browser-scheduled deadline. A 64 MiB SQLite heap limit is not a cap on JavaScript, WASM or total browser memory. Cancel, timeout, failure, changing the file or language, Reset and unmount invalidate work and release the session. No user file content is uploaded, stored or sent to a third-party CDN; first-party application assets still need to load, and downloads can contain sensitive values.
Frequently asked questions
Can I edit the file or enter my own SQL?
No. This viewer reads an in-memory copy and never writes back to the selected file. Selecting a supported ordinary table generates a bounded SELECT; stored definitions are shown as text. It does not run arbitrary user SQL, filters, joins or repairs. Use the separate SQL workbench for CSV/JSON imports, or a suitable local database application for broader SQLite operations.
Why is a valid WAL-mode database refused?
Committed state can depend on a WAL sidecar, and this tool accepts one standalone file only. It rejects a WAL-mode header rather than assume the main file contains the latest state. Ask the source application to produce a consistent standalone rollback-journal-format copy. Do not delete a live application’s journal files to bypass this check.
Why can I see a schema but not its rows?
Views, virtual tables, internal objects and hidden/generated-column tables are schema-only under this viewer’s safety profile. Any virtual table disables row access for the entire database, including its shadow tables. This does not mean the source table is empty or damaged. Inspect the reason label and use the original application when you need unsupported values.
How do I distinguish null, empty text and binary data in an export?
JSON preserves an explicit type and value for every cell. CSV uses N: for null, T: for empty text and B: for empty bytes; other payloads follow their two-character type prefix. An integer 1 is I:1 while the text 1 is T:1. All integer values remain exact decimal text. This typed CSV is deliberately not an ordinary untagged spreadsheet table.
- SQLite: database file format and journaling
- SQLite: table_xinfo and index_xinfo metadata
- SQLite: storage classes and type affinity
- sql.js: browser-local SQLite engine