Skip to content

User activityNetwork

Chrome and Firefox History on macOS

Chrome History and Firefox places.sqlite on macOS: paths, profiles, key tables and epochs to rebuild visits and downloads outside Safari.

Location
~/Library/Application Support/Google/Chrome/Default/History
Proves
Which sites a user opened in Chrome, Chromium browsers or Firefox, when, and what they downloaded
Timestamps
Chrome: microseconds since 1601-01-01 UTC; Firefox PRTime: microseconds since 1970-01-01 UTC
Access
File owner or root; give the collector Full Disk Access as well
Retention
Chrome: about 90 days of visits; Firefox: size-based expiration of old pages
Collection
Aftermath, UAC, mac_apt

What it is

Chrome and Firefox are the most common third-party browsers on macOS, and neither stores anything in Safari's files. Chrome, and every Chromium-based browser (Edge, Brave, Vivaldi, Opera, Arc), keeps each profile's browsing history in a SQLite file simply named History, with separate tables for URLs, visits and downloads. Firefox stores history and bookmarks together in places.sqlite inside a randomly named profile folder.

Both live in the user's ~/Library/Application Support, so they are per-user, survive app updates, and are copied intact by any collector that grabs home directories. Their epochs differ from Safari's, which is the most common source of timeline errors.

Where it lives

BrowserProfile root on macOSMain history file
Chrome~/Library/Application Support/Google/Chrome/<Profile>/History
Edge~/Library/Application Support/Microsoft Edge/<Profile>/History
Brave~/Library/Application Support/BraveSoftware/Brave-Browser/<Profile>/History
Vivaldi~/Library/Application Support/Vivaldi/<Profile>/History
Arc~/Library/Application Support/Arc/User Data/<Profile>/History
Opera~/Library/Application Support/com.operasoftware.Opera/History (single profile layout)
Firefox~/Library/Application Support/Firefox/Profiles/<random>.<name>/places.sqlite, formhistory.sqlite

Chromium profile folders are named Default, Profile 1, Profile 2 and so on, plus Guest Profile. Each profile's Preferences (JSON) holds the profile's display name and settings. Firefox lists its profiles in ~/Library/Application Support/Firefox/profiles.ini.

Protection: the files are owned by the user, so the owner or root can read them. Grant Full Disk Access to the collector anyway, since a collection pass always touches TCC-protected locations too.

What it proves

  • Every recorded visit to a URL with its time, and for Chrome the page that led to it (from_visit) and how it was reached (transition).
  • Typed URLs versus clicked links (Chrome typed_count and transition core type; Firefox typed and visit_type).
  • Downloads: source URL, redirect chain, referrer, target path, size and start/end time (Chrome downloads + downloads_url_chains; Firefox download annotations).
  • Form field entries in Firefox (formhistory.sqlite: fieldname, value, timesUsed, firstUsed, lastUsed).

It does not prove:

  • Incognito or private-window activity (not written to these databases).
  • That a visit came from this Mac when browser sync is enabled; corroborate with local artifacts.
  • That a downloaded file still exists, or was opened.

Key fields

BrowserTableFields
Chromeurlsid, url, title, visit_count, typed_count, last_visit_time, hidden
Chromevisitsid, url (FK to urls.id), visit_time, from_visit, external_referrer_url, transition, visit_duration, is_known_to_sync
Chromedownloadsid, guid, current_path, target_path, start_time, end_time, received_bytes, total_bytes, state, danger_type, opened, last_access_time, referrer, site_url, tab_url, mime_type
Chromedownloads_url_chainsid (FK to downloads.id), chain_index, url
Firefoxmoz_placesid, url, title, visit_count, last_visit_date, typed, hidden, frecency
Firefoxmoz_historyvisitsid, place_id (FK to moz_places.id), visit_date, from_visit, visit_type, source
Firefoxmoz_annos + moz_anno_attributesDownload data: downloads/destinationFileURI, downloads/metaData

Chrome's transition is a bitmask: the low byte (transition & 0xFF) is the core type (link, typed, auto bookmark, reload and so on) and the high bits are qualifiers such as redirects.

Timestamps

BrowserFormatConvert to Unix seconds
Chrome / ChromiumInteger microseconds since 1601-01-01 00:00:00 UTC ("WebKit time")value / 1000000 - 11644473600
FirefoxPRTime: integer microseconds since 1970-01-01 00:00:00 UTCvalue / 1000000

Both are UTC. visit_duration in Chrome is a duration in microseconds, not a timestamp.

-- Chrome visits
SELECT datetime(v.visit_time/1000000 - 11644473600, 'unixepoch') AS visit_utc,
       u.url, u.title, v.transition & 0xFF AS core_transition, v.from_visit
FROM visits v JOIN urls u ON u.id = v.url
ORDER BY v.visit_time;

-- Chrome downloads with full redirect chain
SELECT d.id, datetime(d.start_time/1000000 - 11644473600, 'unixepoch') AS start_utc,
       d.target_path, c.chain_index, c.url
FROM downloads d JOIN downloads_url_chains c ON c.id = d.id
ORDER BY d.start_time, c.chain_index;

-- Firefox visits
SELECT datetime(h.visit_date/1000000, 'unixepoch') AS visit_utc,
       p.url, p.title, h.visit_type
FROM moz_historyvisits h JOIN moz_places p ON p.id = h.place_id
ORDER BY h.visit_date;

Retention

  • Chrome: visits older than roughly 90 days are expired from History; urls rows can linger longer when referenced elsewhere. The user can clear history and downloads at any time.
  • Firefox: history is expired by volume, not a fixed age. Expiration starts when the number of pages exceeds a cap (places.history.expiration.max_pages), and the most recent days of visits are excluded from expiration.
  • Both use SQLite WAL or journal files and leave deleted records in free pages until vacuumed.

Collection

Close the browser if you control the system, or copy the whole profile folder while it runs (Chrome holds a lock on History, so open a copy, never the original). Copy -wal, -shm and -journal companions.

ditto ~/Library/Application\ Support/Google/Chrome /cases/host01/Chrome
ditto ~/Library/Application\ Support/Firefox/Profiles /cases/host01/FirefoxProfiles
  • UAC: chrome.yaml, edge.yaml, brave.yaml and firefox.yaml browser artifacts.
  • Aftermath: collects history, downloads, cookies and extensions for Arc, Brave, Chrome, Edge, Firefox and Safari (root plus Full Disk Access).
  • mac_apt: CHROMIUM plugin (Chrome, Edge, Opera, Vivaldi, Brave, Arc) and FIREFOX plugin, from images or live mounts.

Parsing

  • Hindsight: Chromium-family parser producing a unified timeline from a profile folder, for example python hindsight.py -i "/cases/host01/Chrome/Default" -o host01_chrome.
  • mac_apt: CHROMIUM and FIREFOX plugins covering history, downloads, top sites and Firefox form history.
  • sqlite3 with the queries above for quick triage.

Investigator tips

  • Enumerate every profile and every Chromium browser: Profile 3 of Brave is as relevant as Chrome Default.
  • Chrome downloads_url_chains exposes the full redirect path to a payload, which often reveals the real delivery host behind a link shortener.
  • Match each download to the file's com.apple.quarantine attribute and the quarantine events database; those survive a cleared browser download list.
  • Never mix epochs in one timeline without converting: Chrome's 1601 microseconds, Firefox's Unix microseconds and Safari's 2001 seconds all look like plain big integers.
  • A profile with an empty History but a recent Preferences modification time or many cache files suggests clearing or private use.
  • Use KnowledgeC app-focus records to show the browser was in the foreground during a visit window.

See also