Chrome

Chrome Local Storage

Overview

Chrome implements the Web Storage API's localStorage using Google's LevelDB key-value store rather than SQLite. Each Chrome profile has a single LevelDB database that stores all Local Storage data for all origins, with keys that encode both the web origin and the storage key name.

Local Storage can contain authentication tokens, user preferences, application state, cached data, and other web application data. Unlike cookies, Local Storage data does not expire automatically and is not sent with HTTP requests, making it a preferred location for persistent client-side data in modern web applications.

File Locations

PathDescription
~/Library/Application Support/Google/Chrome/{Profile}/Local Storage/leveldb/LevelDB database directory

LevelDB Directory Structure

Local Storage/leveldb/
├── CURRENT              # Points to the current MANIFEST file
├── LOCK                 # Lock file (indicates active use)
├── LOG                  # Recent operations log (text)
├── LOG.old              # Previous operations log
├── MANIFEST-000001      # Database manifest (SSTable metadata)
├── 000003.log           # Write-ahead log (WAL) with uncommitted data
├── 000004.ldb           # Sorted string table (SSTable) with committed data
└── 000005.ldb           # Additional SSTable

Database Schema / File Format

LevelDB Overview

LevelDB is a log-structured merge tree (LSM) key-value store. Data is organized across:

  • Write-ahead log (.log files): Contains recent writes not yet compacted. May contain data not present in SSTables.
  • Sorted string tables (.ldb files): Immutable, sorted key-value files. Older tables may contain deleted or overwritten values.
  • Manifest (MANIFEST-*): Tracks which SSTables are current and their key ranges.
  • CURRENT: A text file pointing to the active manifest.

Key Format

Local Storage keys in LevelDB follow a specific binary format:

_<origin>\x00<key>
  • The key begins with an underscore (_) prefix byte.
  • The origin (e.g., https://example.com) follows immediately.
  • A null byte (\x00) separates the origin from the storage key name.
  • The storage key name follows the null separator.

Example: _https://github.com\x00user-preferences stores the user-preferences Local Storage key for the https://github.com origin.

Value Encoding

Values are typically encoded as UTF-16LE (Little Endian) strings. Binary detection is performed by checking for non-printable characters after decoding.

Key Fields for Analysis

  • Origin: The web origin that stored the data (extracted from the key prefix). Reveals which sites store persistent data.
  • Key: The storage key name. Application-specific names like auth_token, session, user_data, or preferences indicate the type of data stored.
  • Value: The stored data. May be plain text, JSON, or binary data. Large JSON values often contain rich application state.
  • Value size: The raw byte count of the value before decoding.

Forensically Interesting Keys

Key PatternPotential Content
*token*, *auth*, *session*Authentication tokens and session identifiers
*user*, *profile*, *account*User identity information
*preferences*, *settings*Application configuration
*cache*, *store*, *state*Cached application data
*history*, *recent*In-application activity history
*draft*, *unsaved*Unsaved user input

Timestamps

LevelDB itself does not store timestamps for individual entries. The file modification times of the .ldb and .log files provide approximate timeframes:

FileSignificance
.log filesModification time indicates when recent writes occurred
.ldb filesModification time indicates when compaction created the file
LOG (text)Contains timestamped operation logs from LevelDB

Analysis Notes

  • macfor copies the entire LevelDB directory for forensic preservation, then opens a read-only copy for parsing. This ensures the original data is not modified.
  • The write-ahead log (.log files) may contain data that was written but not yet compacted into SSTables. This can include recently stored or modified values.
  • Deleted keys may still be present in older SSTables as tombstone records. LevelDB does not immediately remove data; it is cleaned up during compaction.
  • Values are truncated to 256 characters in macfor's parsed output (the value_preview field). The full value is preserved in the raw LevelDB files collected in the evidence container.
  • Value types are detected automatically: json for valid JSON strings, text for printable text, and binary for non-printable content.
  • The LOCK file indicates that Chrome had the database open. Its presence in collected evidence means Chrome was running or did not shut down cleanly.
  • Session Storage (Session Storage/ directory) uses the same LevelDB format but is intended for session-scoped data that should be cleared when the tab closes. In practice, data may persist.

Version Differences

The LevelDB Local Storage format has been consistent across Chrome versions. Chrome has explored alternatives (e.g., migrating to a different storage backend) but the LevelDB format remains in use as of Chrome 130+.

Tool Support

ToolCapability
macforCopies raw LevelDB directory, parses key-value entries with origin attribution, detects value types
leveldb-dumpCommand-line tool for dumping LevelDB contents
HindsightIncludes Local Storage parsing in Chrome analysis
ccl_chrome_indexeddbPython library for Chrome LevelDB parsing

References

Previous
Extensions