Quick reference for the on-disk layout and gotchas when reading Chromium's leveldb stores.
A leveldb directory contains:
| File | Purpose |
|---|---|
*.ldb |
Sorted runs (immutable SST tables). Numbered by sequence. |
*.log |
Write-ahead log. Contains recent writes not yet compacted into .ldb. |
MANIFEST-<n> |
Metadata: which .ldb files are live, version edits |
CURRENT |
Tiny pointer file naming the active MANIFEST |
LOCK |
File lock; held by the running app. Blocks readers. |
LOG, LOG.old |
Diagnostic text logs (human-readable) |
To read while the app runs: copy the dir, delete the LOCK file from your copy, open the copy.
LevelDB is log-structured. A write to key foo doesn't overwrite — it appends a new entry. Compaction eventually drops older versions.
When iterating raw records (as ccl_chromium_reader does), you can see multiple entries for the same key. The last one in iteration order is the current value.
# Wrong — uses first match
for rec in ls.iter_records_for_storage_key(origin):
if rec.script_key == "default-model":
return rec.value # might be stale
# Right — iterate all, keep last
latest = {}
for rec in ls.iter_records_for_storage_key(origin):
latest[rec.script_key] = rec.value
return latest["default-model"]
Keys in the underlying leveldb look like:
META:<origin>\x00\x00\x01<script_key>
Values are UTF-8 strings (the actual localStorage.setItem payload). ccl_chromium_localstorage.LocalStoreDb decodes the META prefix and yields (origin, script_key, value) triples.
Same shape but partitioned per browsing session/tab. Use ccl_chromium_sessionstorage.
ccl_chromium_indexeddb.WrappedIndexDB handles all of this. Walk: db.database_ids → db[id] → wdb.object_store_names → wdb[name].iterate_records().
LOCK uses LockFile Win32 API. Robust, no stale locks.flock(2) advisory lock. Crashed apps may leave stale LOCK files; safe to delete.ccl_chromium_reader doesn't take any lock — it just reads the bytes.Local State JSON in the same parent dir contains os_crypt.encrypted_key — DPAPI-encrypted on Windows, used by Chrome to encrypt cookies and saved passwords. Local Storage and IndexedDB themselves are NOT encrypted at rest. They're plain leveldb. Only the cookie store and password store use that key.
| Tool | When |
|---|---|
strings + grep |
Quick grep for known string. No structure needed. |
ccl_chromium_reader |
Structured Local Storage / IndexedDB. Default choice. |
Node level package |
You need to write to leveldb. Better wheels than Python on Windows. |
| Electron remote DevTools | Mutate live state without taking the app down. --remote-debugging-port=<n> then DevTools Protocol. |
leveldb-cli (Go) |
Raw leveldb, no Chromium decoding. Good for non-Chromium leveldb stores. |