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

FilePath
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

FieldForensic Significance
urlFull URL including query parameters and fragments
titlePage title at time of last visit
visit_countTotal visit count across all time
typed1 if user ever typed this URL directly (intentional navigation)
hidden1 if URL is hidden from normal history views (e.g., embedded resources)
frecencyFirefox's combined frequency + recency score (higher = more relevant)
last_visit_datePRTime of most recent visit
rev_hostReversed hostname, useful for domain-based filtering and sorting
guidGlobally unique identifier, useful for cross-device correlation via Firefox Sync

moz_historyvisits Fields

FieldForensic Significance
visit_dateExact PRTime of this specific visit
visit_typeHow the user arrived at the page (see Visit Types below)
from_visitID of the referring visit, enabling navigation chain reconstruction
sessionGroups visits into browsing sessions
sourceVisit 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:

ValueNameDescriptionUser-Initiated
0TRANSITION_LINKUser clicked a linkYes
1TRANSITION_TYPEDUser typed URL in address barYes
2TRANSITION_BOOKMARKUser clicked a bookmarkYes
3TRANSITION_EMBEDEmbedded content (iframes, images, RSS)No
4TRANSITION_REDIRECT_PERMANENTHTTP 301 permanent redirectNo
5TRANSITION_REDIRECT_TEMPORARYHTTP 302/307 temporary redirectNo
6TRANSITION_DOWNLOADDownload initiated (Firefox < 20, legacy)No
7TRANSITION_FRAMED_LINKLink click within a frameNo
8TRANSITION_RELOADPage reloadNo

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 = 1 or typed = 1): Strong evidence of intentional navigation.
  • Bookmark clicks (visit_type = 2): Pre-saved URLs of ongoing interest.
  • Search followed by link (from_visit chain 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_count field 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

VersionChange
Firefox 55Favicons moved to favicons.sqlite (no longer in places.sqlite)
Firefox 62moz_origins table added for origin-based grouping
Firefox 115source 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

ToolCapability
macforFull places.sqlite parsing with visit type classification and input history (Pro module)
DB Browser for SQLiteManual query execution against places.sqlite
plaso/log2timelineFirefox history parser producing timeline events
AXIOMAutomated Firefox history extraction and timeline
firefedSpecialised Firefox forensic tool with history support

References

Previous
Firefox Overview