Firefox places.sqlite forensics
2026-06-21 · 4 min
places.sqlite is the single most useful file in a Firefox profile. Unlike
Chrome, which splits history and bookmarks across separate stores, Firefox
keeps both in one SQLite database — plus the visit graph that links them.
Learn its two core tables and you can reconstruct a browsing timeline, the
referrer chain that led to each page, and which URLs the user deliberately
saved.
The schema you actually need
places.sqlite has a dozen tables, but two carry the case.
| Table | Role |
|---|---|
moz_places | One row per distinct URL — the hub |
moz_historyvisits | One row per visit to a URL |
moz_bookmarks | Bookmark tree; joins to moz_places for URLs |
moz_annos | Per-place annotations, including downloads |
moz_origins | Host/scheme breakdown (newer profiles) |
moz_places is keyed by id and holds the URL-level facts:
| Column | Meaning |
|---|---|
url | The full URL |
title | Last-seen page title |
visit_count | Number of recorded visits |
last_visit_date | PRTime of the most recent visit |
frecency | Frequency + recency ranking score |
rev_host | Host reversed (moc.elpmaxe.) for suffix indexing |
rev_host trips people up: www.example.com is stored as
moc.elpmaxe.www. so Firefox can index by domain suffix. Reverse it back
before you report it.
Per-visit detail and the referrer chain
moz_historyvisits is where the timeline lives. Each row records one visit:
| Column | Meaning |
|---|---|
place_id | Foreign key → moz_places.id |
visit_date | PRTime of this visit |
visit_type | How the visit happened (see below) |
from_visit | id of the visit that referred this one |
from_visit is the gold. It points at the previous visit row, so you can
walk the chain backwards and prove how the user reached a page — clicked a
link, followed a redirect, or typed the address. A typed visit with no
referrer is a deliberate navigation; a link visit with a from_visit set
shows the click that produced it.
visit_type values
The visit_type integer tells you the navigation source. Filter it
carefully — embed and framed_link visits are usually noise (ads,
trackers, iframes), not user intent.
| Value | Type | Notes |
|---|---|---|
| 1 | link | Followed a link |
| 2 | typed | User typed the URL — strong intent signal |
| 3 | bookmark | Opened from a bookmark |
| 4 | embed | Embedded resource; not top-level |
| 5 | redirect_permanent | 301 |
| 6 | redirect_temporary | 302 |
| 7 | download | Download initiated |
| 8 | framed_link | Link followed inside a frame |
| 9 | reload | Page reload |
For a defensible "the user intentionally visited X" claim, lean on
visit_type 2 (typed) and 3 (bookmark), then corroborate with the
from_visit chain.
Timestamps: PRTime
Every timestamp in places.sqlite is PRTime — microseconds since the
Unix epoch (1970-01-01 UTC). This is the most common parsing error on
Firefox cases: people apply Chrome's WebKit epoch (1601) or treat the value
as milliseconds and land decades off.
unix_seconds = visit_date / 1000000
So 1718928000000000 is 2024-06-21 00:00:00 UTC, not the year 56000-something.
See the timestamp formats post for the full epoch matrix.
Bookmarks and downloads
Bookmarks live in moz_bookmarks as a tree (folders, separators, and
bookmark nodes), joined to moz_places through fk for the actual URL.
A saved bookmark is a strong intent artifact — the user chose to keep it.
Downloads are not in their own table. Firefox records them as annotations on
the originating place: look in moz_annos for the
downloads/destinationFileURI annotation, which carries the local path the
file was saved to. That ties a downloaded file back to the URL and visit
that produced it.
Acquisition: don't skip the WAL
places.sqlite runs in WAL mode. Recent visits, bookmarks, and downloads
may sit in the places.sqlite-wal sidecar and never appear if you parse the
main file alone. Always grab places.sqlite, places.sqlite-wal and
places.sqlite-shm together, with matching base names. The same trap that
loses recent Chrome history loses recent Firefox history.
BrowserForensics parses places.sqlite directly in the browser — history,
bookmarks, the visit timeline and downloads — and applies the WAL so the
most recent activity is included.