browserforensics
Back to all articles

Chrome Local State as a forensic artifact

2026-06-21 · 3 min

Local State gets opened, the os_crypt key gets copied, and the rest of the file gets closed again. That is a missed read. The same JSON enumerates every profile on the machine and the Google account behind each one, records which profile was last active, and stamps the build. Decryption is one of the things Local State does for you, not the only thing.

One file, at the User Data root

Local State is a single JSON file per browser install — it sits at the root of the User Data directory, not inside a profile. There is one for the whole installation, regardless of how many profiles exist. Edge is identical:

%LOCALAPPDATA%\Google\Chrome\User Data\Local State
%LOCALAPPDATA%\Microsoft\Edge\User Data\Local State

Because it lives at the root, it is the natural index for a multi-profile machine: open it first and you know how many profiles you are dealing with before you touch any of them.

The encryption key (os_crypt)

The part everyone already reaches for:

{
  "os_crypt": {
    "encrypted_key": "RFBBUEkBAAAA0Iyd3wEV0RGM...",
    "app_bound_encrypted_key": "QVBQQgEAAADQ..."
  }
}
  • encrypted_key is base64. Decode it and the first five bytes are the ASCII tag DPAPI; strip it and what remains is the AES key wrapped under the user's Windows credentials.
  • app_bound_encrypted_key (Chrome 127+) carries the APPB tag and holds the app-bound key used for v20 cookies and passwords.

This is the key that decrypts cookies, passwords and payment cards. It is wrapped, so you cannot read it out directly — the offline DPAPI chain covers the unwrap, and the cookie encryption post covers what the key then decrypts.

profile.info_cache — the profile roster

This is the part that gets skipped. profile.info_cache is a map of every profile the browser knows about, keyed by directory name (Default, Profile 1, …). Each entry includes:

{
  "profile": {
    "info_cache": {
      "Profile 1": {
        "name": "Work",
        "user_name": "j.doe@contoso.com",
        "gaia_id": "1078...4421",
        "gaia_name": "Jane Doe",
        "is_using_default_avatar": false,
        "active_time": 1718900000.0
      }
    }
  }
}
  • user_name is the Google account email signed into that profile.
  • gaia_id / gaia_name are the account's stable Google identifier and display name.
  • active_time is roughly when the profile was last used.

So a single file ties each profile directory to a real person's email and account ID — before you have parsed a single cookie or history row. For the per-profile sign-in detail behind these fields, see Preferences and account forensics.

Last used and last active

Two sibling keys answer "which profile was actually in use":

  • profile.last_used — the directory name of the profile open most recently.
  • profile.last_active_profiles — the set of profiles that were open in the last session.

On a machine with a personal and a work profile, this is what tells you which identity the user was operating under, not just which ones exist.

Browser metadata

Local State also stamps the install: the browser version, the install date, and the active variations/experiments (feature flags the build was running). Version and install date help you reason about which encryption scheme to expect — pre-v80, v10, or v20 app-bound — and bound the timeline of the install itself.

What the tool surfaces

The tool parses Local State and lays out both halves: it enumerates the profiles with their emails, gaia_ids and last-active times, flags the last-used profile, and surfaces the wrapped encrypted_key / app_bound_encrypted_key so they feed straight into the decryption workflow. One artifact answers "who, which profile, and what is the key" in a single read. For where everything else lives once you know the profile layout, see where browsers store their artifacts.

Further reading