Firefox
Firefox History
Overview
Firefox browsing history is stored in places.sqlite, a unified database that also contains bookmarks, download annotations, and URL metadata. History data spans two primary tables: moz_places (URL metadata) and moz_historyvisits (individual visit records). A third table, moz_inputhistory, tracks what users typed in the address bar before selecting a URL from autocomplete suggestions.
Unlike Chrome, which stores one history row per URL, Firefox creates a separate moz_historyvisits row for every individual page visit. A URL visited 50 times will have one moz_places row and 50 moz_historyvisits rows, each with its own timestamp, visit type, and referrer chain. This makes Firefox history particularly valuable for detailed timeline reconstruction.
File Locations
| File | Path |
|---|---|
| History database | ~/Library/Application Support/Firefox/Profiles/{profile}/places.sqlite |
| WAL journal | ~/Library/Application Support/Firefox/Profiles/{profile}/places.sqlite-wal |
| Shared memory | ~/Library/Application Support/Firefox/Profiles/{profile}/places.sqlite-shm |
The WAL (Write-Ahead Log) file may contain recent visits not yet checkpointed to the main database. Always collect and examine all three files.
Database Schema
moz_places (URL Storage)
CREATE TABLE moz_places (
id INTEGER PRIMARY KEY,
url LONGVARCHAR,
title LONGVARCHAR,
rev_host LONGVARCHAR, -- Reversed hostname (e.g., "moc.elpmaxe.")
visit_count INTEGER DEFAULT 0,
hidden INTEGER DEFAULT 0 NOT NULL,
typed INTEGER DEFAULT 0 NOT NULL,
frecency INTEGER DEFAULT -1 NOT NULL,
last_visit_date INTEGER, -- PRTime (microseconds since Unix epoch)
guid TEXT,
foreign_count INTEGER DEFAULT 0 NOT NULL,
url_hash INTEGER DEFAULT 0 NOT NULL,
description TEXT,
preview_image_url TEXT,
origin_id INTEGER REFERENCES moz_origins(id),
site_name TEXT
);
moz_historyvisits (Visit Records)
CREATE TABLE moz_historyvisits (
id INTEGER PRIMARY KEY,
from_visit INTEGER, -- Referring visit ID (navigation chain)
place_id INTEGER NOT NULL, -- Foreign key to moz_places.id
visit_date INTEGER NOT NULL, -- PRTime (microseconds since Unix epoch)
visit_type INTEGER NOT NULL, -- Visit transition type (0-8)
session INTEGER DEFAULT 0 NOT NULL, -- Session grouping
source INTEGER DEFAULT 0 NOT NULL, -- Visit source (Firefox 115+)
triggeringPlaceId INTEGER -- Triggering place (Firefox 115+)
);
moz_inputhistory (Address Bar Input)
CREATE TABLE moz_inputhistory (
place_id INTEGER NOT NULL, -- Foreign key to moz_places.id
input LONGVARCHAR NOT NULL, -- Partial text typed by user
use_count INTEGER, -- Decaying relevance score (float stored as int)
PRIMARY KEY (place_id, input)
);
moz_origins (Firefox 62+)
CREATE TABLE moz_origins (
id INTEGER PRIMARY KEY,
prefix TEXT NOT NULL, -- "http://", "https://"
host TEXT NOT NULL,
frecency INTEGER NOT NULL,
UNIQUE (prefix, host)
);
Key Fields for Analysis
moz_places Fields
| Field | Forensic Significance |
|---|---|
url | Full URL including query parameters and fragments |
title | Page title at time of last visit |
visit_count | Total visit count across all time |
typed | 1 if user ever typed this URL directly (intentional navigation) |
hidden | 1 if URL is hidden from normal history views (e.g., embedded resources) |
frecency | Firefox's combined frequency + recency score (higher = more relevant) |
last_visit_date | PRTime of most recent visit |
rev_host | Reversed hostname, useful for domain-based filtering and sorting |
guid | Globally unique identifier, useful for cross-device correlation via Firefox Sync |
moz_historyvisits Fields
| Field | Forensic Significance |
|---|---|
visit_date | Exact PRTime of this specific visit |
visit_type | How the user arrived at the page (see Visit Types below) |
from_visit | ID of the referring visit, enabling navigation chain reconstruction |
session | Groups visits into browsing sessions |
source | Visit source (Firefox 115+): 0 = local, other values for Sync origins |
Frecency Score
Frecency is Firefox's proprietary relevance ranking that combines frequency (how often) with recency (how recently). It is used for address bar autocomplete suggestions. Key points:
- Higher values indicate more frequently and recently accessed URLs.
- Values decay over time automatically.
- Typed URLs receive higher frecency boosts than link clicks.
- A value of -1 indicates the URL has never been visited (e.g., bookmarked but unvisited).
- Typical range: 0 to ~10,000+ for heavily visited sites.
Visit Types
Firefox uses integer codes in moz_historyvisits.visit_type to classify how each page was reached:
| Value | Name | Description | User-Initiated |
|---|---|---|---|
| 0 | TRANSITION_LINK | User clicked a link | Yes |
| 1 | TRANSITION_TYPED | User typed URL in address bar | Yes |
| 2 | TRANSITION_BOOKMARK | User clicked a bookmark | Yes |
| 3 | TRANSITION_EMBED | Embedded content (iframes, images, RSS) | No |
| 4 | TRANSITION_REDIRECT_PERMANENT | HTTP 301 permanent redirect | No |
| 5 | TRANSITION_REDIRECT_TEMPORARY | HTTP 302/307 temporary redirect | No |
| 6 | TRANSITION_DOWNLOAD | Download initiated (Firefox < 20, legacy) | No |
| 7 | TRANSITION_FRAMED_LINK | Link click within a frame | No |
| 8 | TRANSITION_RELOAD | Page reload | No |
Visit types 0, 1, and 2 are considered user-initiated and are the most forensically significant for establishing user intent. Redirect visits (4, 5) are important for tracking the full navigation path. Embed visits (3) are typically hidden from history views.
Timestamps
All timestamps in moz_places and moz_historyvisits use PRTime: microseconds since 1970-01-01 00:00:00 UTC.
Conversion formula:
UTC datetime = PRTime value / 1,000,000 -> Unix timestamp -> datetime
Example:
visit_date = 1706234567123456
Unix seconds = 1706234567123456 / 1000000 = 1706234567.123456
Result = 2024-01-25T22:22:47.123456Z
A value of 0 or NULL means no timestamp is recorded (e.g., a bookmarked URL never visited has last_visit_date = NULL).
Analysis Notes
Reconstructing Navigation Chains
The from_visit field in moz_historyvisits creates a linked list of navigation steps. To reconstruct a user's browsing path:
-- Find navigation chain leading to a specific visit
WITH RECURSIVE chain AS (
SELECT id, from_visit, place_id, visit_date, visit_type
FROM moz_historyvisits
WHERE id = ? -- Start from a specific visit
UNION ALL
SELECT v.id, v.from_visit, v.place_id, v.visit_date, v.visit_type
FROM moz_historyvisits v
JOIN chain c ON c.from_visit = v.id
)
SELECT c.*, p.url, p.title
FROM chain c
JOIN moz_places p ON p.id = c.place_id
ORDER BY c.visit_date;
Identifying User Intent
Combine visit type analysis with the typed flag:
- Typed URLs (
visit_type = 1ortyped = 1): Strong evidence of intentional navigation. - Bookmark clicks (
visit_type = 2): Pre-saved URLs of ongoing interest. - Search followed by link (
from_visitchain from typed Google/Bing search to link click): Search-driven navigation. - Redirects (
visit_type = 4, 5): May indicate ad tracking, URL shorteners, or phishing redirects.
Input History Forensics
The moz_inputhistory table reveals what users typed in the address bar before selecting an autocomplete suggestion. This can show:
- Partial searches that led to specific URLs.
- Frequently used URL shortcuts.
- The
use_countfield uses a decay algorithm and is stored as a float, so values decrease over time.
Useful Queries
Most visited sites:
SELECT url, title, visit_count, frecency, last_visit_date
FROM moz_places
WHERE visit_count > 0
ORDER BY visit_count DESC
LIMIT 100;
History within a time range (PRTime):
SELECT p.url, p.title, v.visit_date, v.visit_type
FROM moz_places p
JOIN moz_historyvisits v ON v.place_id = p.id
WHERE v.visit_date BETWEEN ? AND ?
ORDER BY v.visit_date;
Only user-initiated visits:
SELECT p.url, p.title, v.visit_date, v.visit_type
FROM moz_places p
JOIN moz_historyvisits v ON v.place_id = p.id
WHERE v.visit_type IN (0, 1, 2)
ORDER BY v.visit_date DESC;
Version Differences
| Version | Change |
|---|---|
| Firefox 55 | Favicons moved to favicons.sqlite (no longer in places.sqlite) |
| Firefox 62 | moz_origins table added for origin-based grouping |
| Firefox 115 | source and triggeringPlaceId columns added to moz_historyvisits |
The collector handles missing columns gracefully. If moz_origins or the newer moz_historyvisits columns are absent, collection proceeds with available fields.
Tool Support
| Tool | Capability |
|---|---|
| macfor | Full places.sqlite parsing with visit type classification and input history (Pro module) |
| DB Browser for SQLite | Manual query execution against places.sqlite |
| plaso/log2timeline | Firefox history parser producing timeline events |
| AXIOM | Automated Firefox history extraction and timeline |
| firefed | Specialised Firefox forensic tool with history support |