01Location
- <User Data>/<Profile>/History
- %LOCALAPPDATA%\Google\Chrome\User Data\Default\History
- ~/Library/Application Support/Google/Chrome/Default/History
- ~/.config/google-chrome/Default/History
02Questions it answers
- Which URLs were visited, when, and how often?
- Was a page reached by typing, a link, a bookmark, a form submission or a reload?
- Which files were downloaded, from which URL chain and referrer, and where were they saved?
- Which search terms were entered through the address bar?
- Did a visit originate on another device synced to the same account?
03Format and versions
| Format | SQLite 3 database written through Chromium's //sql layer. Times are 64-bit integers of microseconds since 1601-01-01 UTC (base::Time serialised with BindTime). |
|---|---|
| Applies to | Chromium main branch as read on 2026-10-14. Columns were added over many schema versions; older databases can lack newer columns such as opener_visit or the originator_* fields. |
04Key fields
| Field | What it tells you |
|---|---|
| urls (id, url, title, visit_count, typed_count, last_visit_time, hidden) | One row per URL with aggregate counters; visits.url points to urls.id. |
| visits (id, url, visit_time, from_visit, transition, visit_duration) | One row per visit. from_visit links to the referring visit; transition holds the page transition type. |
| visits.transition | Core type in the low byte (mask 0xFF): 0 LINK, 1 TYPED, 2 AUTO_BOOKMARK, 3 AUTO_SUBFRAME, 4 MANUAL_SUBFRAME, 5 GENERATED, 6 AUTO_TOPLEVEL, 7 FORM_SUBMIT, 8 RELOAD, 9 KEYWORD, 10 KEYWORD_GENERATED; upper bits are qualifiers such as FROM_ADDRESS_BAR or redirect flags. |
| visits.originator_cache_guid / originator_visit_id | For visits synced from another machine: the originating client's identifier and its local visit id. Local visits write an empty string and 0. |
| downloads (guid, current_path, target_path, start_time, end_time, received_bytes, total_bytes, state, danger_type, opened, last_access_time, referrer, tab_url, mime_type) | One row per download. state: 0 in progress, 1 complete, 2 cancelled, 4 interrupted. opened is 1 if the file was ever opened from the browser. |
| downloads_url_chains (id, chain_index, url) | Redirect chain for a download: chain_index 0 is the initial target and the highest index the final URL after redirects. |
| keyword_search_terms (keyword_id, url_id, term, normalized_term) | Search terms entered for a search engine keyword, linked to the resulting urls row. |
05Timestamps
| Field | Encoding | Note |
|---|---|---|
| urls.last_visit_time, visits.visit_time | Chromium/WebKit time: int64 µs since 1601-01-01 UTC | Unix µs = value − 11644473600000000. base::Time follows the OS wall clock and can jump when the clock is adjusted. |
| visits.visit_duration | int64 µs duration (TimeDelta) | A length of time, not a date; do not convert it with the 1601 epoch. |
| downloads.start_time, end_time, last_access_time | Chromium/WebKit time: int64 µs since 1601-01-01 UTC | Migration code shows that very old schemas stored time_t seconds and were converted on upgrade. |
Decode raw values with the Timestamp decoder and convert local wall-clock times with the Local time to UTC.
06Examination workflow
- Work on a copy of History together with any -journal or -wal file present in the profile folder.
- Join visits.url to urls.id and convert visit_time to UTC; keep the raw integer next to the converted value.
- Decode transition with the 0xFF core mask and list the qualifier bits separately.
- Rebuild download chains from downloads_url_chains and compare target_path with the file system.
- Separate locally made visits from synced ones using the originator_* columns before attributing activity to this device.
07Interpretation pitfalls
- The history backend expires entries older than 90 days (kExpireDaysThreshold), so absence of an old visit is expected.
- visit_count and typed_count are aggregates and can disagree with the visits rows that remain after expiry or deletion.
- Synced visits from other devices can appear in the same tables; the originator columns distinguish them only in schemas that have them.
- A visit records that the browser loaded a URL, not that a person read the page.
09Sources
- Chromium source — components/history/core/browser/url_database.cc The Chromium Authors (GitHub mirror) · checked 2026-10-14
- Chromium source — components/history/core/browser/visit_database.cc The Chromium Authors (GitHub mirror) · checked 2026-10-14
- Chromium source — components/history/core/browser/download_database.cc The Chromium Authors (GitHub mirror) · checked 2026-10-14
- Chromium source — components/history/core/browser/download_constants.h The Chromium Authors (GitHub mirror) · checked 2026-10-14
- Chromium source — ui/base/page_transition_types.h The Chromium Authors (GitHub mirror) · checked 2026-10-14
- Chromium source — history_backend.h (kExpireDaysThreshold) The Chromium Authors (GitHub mirror) · checked 2026-10-14
- Chromium source — components/history/core/browser/history_constants.cc The Chromium Authors (GitHub mirror) · checked 2026-10-14
- Chromium source — sql/statement.cc (BindTime / ColumnTime) The Chromium Authors (GitHub mirror) · checked 2026-10-14
- Chromium source — base/time/time.h (base::Time) The Chromium Authors (GitHub mirror) · checked 2026-10-14
- Chromium source — docs/user_data_dir.md (User Data Directory) The Chromium Authors (GitHub mirror) · checked 2026-10-14