browserforensics
Back to all articles

Firefox form history forensics

2026-06-21 · 3 min

formhistory.sqlite is one of the highest-signal artifacts in a Firefox profile and one of the most overlooked. It captures the literal text a user typed into web forms and the search bar — emails, usernames, addresses, search queries — each with a usage count and first/last-used timestamps. Where history tells you which pages were visited, form history often tells you who the user is and what they were after.

Where it lives

formhistory.sqlite sits in the Firefox profile root, alongside places.sqlite and cookies.sqlite. See Firefox history file locations for the per-OS profile paths.

It is Firefox's equivalent of Chrome's autofill store. If you work both browsers, the Chrome Web Data / autofill post covers the Chromium side of the same behaviour.

The moz_formhistory table

A single table carries everything:

ColumnMeaning
idRow identifier
fieldnameThe form field's name attribute (e.g. email, q, search)
valueThe exact text the user typed
timesUsedHow many times this value was entered/reused
firstUsedFirst time this value was saved
lastUsedMost recent time it was used
guidSync identifier

The pairing of fieldname and value is what makes this artifact so useful. A fieldname of email with a value of an address is a strong identity indicator; a fieldname of q or search is almost always a search-bar or site-search query, exposing intent in the user's own words.

The tool parses moz_formhistory directly and surfaces field, value, timesUsed, and the first/last-used timestamps per row.

What the values reveal

  • Identity — emails, usernames, full names, phone numbers and postal addresses typed into signup and checkout forms.
  • Intent — search-bar queries and on-site searches. These are free-text and frequently more candid than visited URLs.
  • Aliases — multiple values under the same fieldname (several emails or usernames) suggest separate accounts or personas.
  • FrequencytimesUsed ranks how often a value was reused, which helps separate a primary identity from a one-off entry.

Because these are values the user typed rather than pages they landed on, they survive even when browsing history has been cleared, as long as form history itself was not also wiped.

Timestamps

firstUsed and lastUsed are stored as PRTime — microseconds since the Unix epoch (1970). Divide by 1,000,000 for seconds before converting. This is the same convention used across most of places.sqlite; the browser timestamp formats post documents the per-column exceptions you will hit elsewhere in Firefox.

firstUsed anchors when a value entered the profile; lastUsed shows the most recent reuse. Together with timesUsed, they let you place a value on a timeline and gauge its weight in the case.

Pitfalls

  • A high timesUsed does not prove deliberate typing — autocomplete selection also increments it. Treat the count as reuse evidence, not keystroke evidence.
  • fieldname is attacker-controlled site markup, not a fixed taxonomy. Two sites may both call a field q or user; do not assume a single field name maps to a single meaning across the whole table.
  • Form history can be cleared independently of history. An empty or missing formhistory.sqlite next to a populated places.sqlite is itself worth noting.
  • Like other Firefox SQLite stores it can run with WAL; pull the -wal and -shm sidecars together to avoid missing recent rows.

Further reading