ByteScope

SQLite database file format

A SQLite database file, a self-contained embedded SQL database.

MIME type
application/vnd.sqlite3
Extensions
.sqlite, .db, .sqlite3
Category
Data & databases

Magic-number signature

0x0000000053514C69746520666F726D6174203300SQLite format 3·'SQLite format 3\0' header

About the SQLite database format

A SQLite database is a sequence of fixed-size pages, all the same size, with the first hundred bytes of page one given over to a header that describes the whole file. Everything else — tables, indexes, the schema itself — is a B-tree of those pages, and the schema is simply a table called sqlite_schema stored on page one like any other. That uniformity is why the format is so stable: a file written by SQLite 3.0 in 2004 still opens today, and the project has committed to keeping it readable through 2050.

Header layout, byte by byte

OffsetLengthFieldMeaning
016Header stringThe ASCII text 'SQLite format 3' followed by a NUL byte — sixteen bytes exactly. The 3 is the file-format generation, not the library version, and it has not changed since 2004.
162Page sizeBig-endian, and one of the very few big-endian formats you will meet on a desktop. A power of two between 512 and 32768, or the literal value 1 meaning 65536 because that will not fit in two bytes. 4096 is the modern default, so this field usually reads 10 00.
181File format write version1 for the legacy rollback journal, 2 for write-ahead logging. A database in WAL mode needs its companion -wal and -shm files to be complete, which is why copying only the .db of a live database can lose recent commits.
191File format read version1 or 2 with the same meaning. A value above 2 tells an old library that the file uses something it does not understand, and it must refuse rather than guess.
201Reserved space per pageBytes left unused at the end of every page, normally 0. Encryption extensions such as SEE set it to make room for a per-page nonce and authentication tag, so a non-zero value here on a file you cannot open is the explanation.
211Maximum embedded payload fractionMust be 64. It is a tuning knob that was never made adjustable, so any other value means the header is damaged rather than exotic.
221Minimum embedded payload fractionMust be 32. Together with the byte above and below it, these three constants are the cheapest integrity check the header offers — 64, 32, 32 in a row.
231Leaf payload fractionMust be 32. Fixed for the same historical reason: the values were meant to be configurable and never were.
244File change counterIncremented on every transaction that modifies the file. Readers use it to notice that a cached page is stale, so it is also the quickest way to see whether a database has been written to since you last looked.
284Database size in pagesThe in-header size. It is only trustworthy when it matches the version-valid-for number at offset 92; otherwise the true size is the file length divided by the page size, because an older library wrote to the file without maintaining this field.
324First freelist trunk pagePage number where the list of unused pages begins, or 0 if there is none. Deleted rows leave their pages on this list rather than shrinking the file, which is why a database never gets smaller until VACUUM runs.
364Freelist page countHow many pages are on that list. A large number against a small database is the signature of a file that has had a lot of data deleted and is holding onto the space — and of deleted rows still recoverable in a hex editor.
404Schema cookieBumped whenever the schema changes. Prepared statements record the value they were compiled against and are recompiled automatically when it moves, which is how SQLite handles an ALTER TABLE under a live connection.
444Schema format number1 through 4. 4 is current and has been the default since 2006; it is what enables DESC indexes and the boolean literals. An old library reading a format it does not know refuses the file rather than misreading it.
484Default page cache sizeA suggestion for the page cache, set by PRAGMA default_cache_size. Advisory only — the library is free to ignore it, and modern versions largely do.
524Largest root b-tree pageNon-zero only in auto-vacuum or incremental-vacuum mode, where it records the largest root page so that pointer maps can be maintained. Zero means the database will never shrink on its own.
564Text encoding1 for UTF-8, 2 for UTF-16 little-endian, 3 for UTF-16 big-endian. Set once when the database is created and immutable afterwards. UTF-8 is what essentially everything writes, and reading strings with the wrong assumption here is what produces a database full of mojibake.
604User versionUntouched by SQLite itself; read and written by PRAGMA user_version. Applications use it as a schema migration counter, which makes it one of the most useful four bytes in the file when you are trying to work out which version of an app wrote a database.
644Incremental vacuum modeNon-zero when incremental-vacuum is in effect, and meaningful only when the largest-root-page field at offset 52 is also non-zero.
684Application IDSet by PRAGMA application_id so that a program can claim a database file as its own format. It is what lets a detector say 'this is a Firefox places database' rather than merely 'this is SQLite', when the application bothered to set it.
7220Reserved for expansionTwenty bytes that must be zero. They have stayed zero for two decades, so a non-zero run here is a reliable sign that something has written over the header.
924Version valid for numberThe value the change counter had when the version number below was last written. When it does not equal the change counter at offset 24, an older library has modified the file and the in-header size at offset 28 must not be trusted.
964SQLITE_VERSION_NUMBERThe library version that last wrote the file, encoded as major times one million plus minor times one thousand plus patch. 0x002E8DF8 is 3051000, meaning SQLite 3.51.0 — four bytes that tell you exactly which build touched the database last.

Telling it apart from its neighbours

Easily confused withHow to tell
WAL modeByte-identical for the first sixteen bytes; the difference is the pair of bytes at offsets 18 and 19, which read 2 rather than 1. It matters because the newest committed data may not be in the .db file at all — it is in the companion -wal file — so copying only the database silently loses transactions. Checkpoint first, or copy all three files together.
Encrypted SQLiteSQLCipher and similar tools encrypt the whole file including the header, so offset 0 is random-looking bytes and no detector will call it SQLite at all. The SEE extension takes the opposite approach and leaves the header readable while setting the reserved-space byte at offset 20 non-zero. A file that identifies as SQLite and still will not open is worth checking at offset 20.
OLE2 / CFBThe two general-purpose 'filesystem in a file' formats. SQLite opens with sixteen bytes of readable ASCII; a Compound File Binary container opens D0 CF 11 E0 A1 B1 1A E1. Both use fixed-size pages, both keep a free list, and both survive partial writes badly — but SQLite's format is public, versioned and documented field by field, which CFB's was not for its first fifteen years.
ParquetThe pairing that comes up whenever someone asks which single-file format to ship data in. Parquet is columnar, immutable and marked at both ends with 'PAR1'; SQLite is row-oriented, transactional and updatable in place. Parquet wins decisively on scanning one column of a billion rows; SQLite wins on anything that needs indexes, joins, or writing a row back.

How these files break

  • A -wal or -journal file that was lost. The database itself is completely intact and readers still fail or silently roll back, because a transaction was in flight when the copy was made. This is not damage to the .db at all — it is an incomplete copy — and it is the single most common way people corrupt a SQLite database.
  • A file copied while being written. Because a commit touches several pages, snapshotting the file mid-transaction captures a mixture of old and new pages that no consistent state ever contained. The header parses perfectly, the page count is plausible, and a B-tree walk falls off into a page that belongs to another table. Use the backup API or VACUUM INTO rather than cp.
  • Text-mode transfer or an editor that rewrote the file. Every multi-byte field is binary, and the header's own ASCII prefix contains no 0D 0A, so it survives untouched while every page boundary after it shifts. The file is still identified as SQLite and is unreadable from the first page onward.
  • A truncated download. The header at offset 28 declares a page count larger than the file can hold, which is precisely the case SQLite checks: compare the declared size against the file length divided by the page size at offset 16. A short file may still open read-only and serve every table whose pages happened to land before the cut.
  • Header bytes overwritten by another program. The three constants at offsets 21, 22 and 23 must read 64, 32, 32, and the twenty bytes at offset 72 must be zero. Those are the cheapest tests for a header that has been trampled, and they catch the case where a file has been written to by something that thought it owned the name.

Where the format stands today

SQLite is the most widely deployed database engine in existence and it is not going anywhere: every Android and iOS device, every mainstream browser, macOS, countless desktop applications and a great deal of embedded firmware all keep their state in SQLite files. It is first choice whenever the data has structure, needs querying, and lives on one machine — application settings, caches, message histories, offline stores, local analytics — because it gives real transactions and real SQL with no server, no configuration and no network. It is the wrong choice when many machines must write concurrently, since its locking is file-based and a network filesystem breaks it, and that is the boundary where PostgreSQL or MySQL start. It is also increasingly used as an application file format rather than a database: a single .sqlite carries a whole project, is updatable in place without rewriting, and survives a crash mid-save in a way that a custom binary format almost never does. Given the format's documented stability guarantee and the fact that its own test suite is larger than the library, it is a reasonable thing to bet an archive on.

Open SQLite database files on this site

Every one of these runs in your browser — the file never leaves your machine.

Related formats

Formats that are easy to confuse with SQLite database — compare their leading bytes.

FormatFirst bytesExtension
Parquet50 41 52 31.parquet
OLE2 / CFBD0 CF 11 E0 A1 B1.doc

Frequently asked questions

What is a magic number in a file?

The first few bytes of a file, which identify its format regardless of what the name says. A PNG always starts with 89 50 4E 47; a ZIP with 50 4B 03 04. Operating systems, browsers and the file command all read these bytes rather than trusting the extension, which is why renaming a file does not change what it actually is.

How do I check a file's magic number myself?

On macOS or Linux, xxd -l 16 yourfile prints the first 16 bytes; on Windows, Format-Hex -Path yourfile -Count 16 in PowerShell. Or drop the file into the File Type Identifier on this site, which reads the bytes locally and names the format for you — nothing is uploaded.

Why do two formats share the same magic number?

Because one is built on the other. Every docx, xlsx, pptx, apk, jar and epub begins with the ZIP signature, since all of them are ZIP archives underneath; telling them apart means looking at the entries inside. Java class files and macOS universal binaries both start with CA FE BA BE and are distinguished by the field that follows.

Can a file have no magic number at all?

Yes. Text-based formats — XML, HTML, JSON, SVG, CSV — have no fixed byte signature, so they are recognized structurally instead: a leading <?xml declaration, a <svg element, or a { followed by a quoted key. That detection is a good guess rather than a certainty, which is why this reference marks those formats as probe-detected.

Does a matching magic number mean the file is safe?

No. It tells you what the format is, not whether the contents are harmless — a genuine PDF or docx can still carry a malicious payload. Identifying the true type is a useful first check, especially when the extension disagrees with the bytes, but it is not a malware scan.

Have a file that might be in the SQLite database format? Identify it with the File Type Identifier — it reads the magic number locally, nothing is uploaded. Or browse all formats.