Recovering browser history (URLs, cookies, autofill) from pagefile.sys
5/20/2026 · 5 min read
Browsers are the noisiest applications on a Windows host. Hundreds of tabs over a session, HTTPS streams decrypted into plaintext buffers, autofill and cache state held in memory for the entire lifetime of the process, SQLite databases updated constantly. When memory pressure hits, something gets evicted, and that something is very often browser data. Even hosts with InPrivate or Incognito sessions, where nothing was supposed to persist, leak through this path because the kernel does not know which renderer is private.
This is also the channel I rely on when the live profile is corrupt, encrypted, or already wiped, and the browser history workflow has nothing to work with on disk.
What you can recover
In rough order of frequency in a typical user pagefile:
- Visited URLs.
https://...strings from the address bar, click targets, HTTP fetch headers. - Search queries.
https://www.google.com/search?q=...,https://duckduckgo.com/?q=..., Bing. The query stays in the URL. - Form submissions.
application/x-www-form-urlencodedbodies survive briefly in renderer heap. - Cookies.
Cookie:andSet-Cookie:HTTP header fragments. - Autofill values. Usernames, addresses, credit card numbers, phone numbers. Chrome and Edge keep these in
Web DataSQLite, decrypted into RAM when filling a form. - SQLite database fragments. Pages from
History,Cookies,Login Data,Web Data. - JWT and session tokens in cached XHR / fetch responses. See finding credentials for the broader sweep.
Browser file layouts
Where browser data lives on disk, useful for cross-referencing what you find in the pagefile:
| Browser | Profile root |
|---|---|
| Chrome | %LOCALAPPDATA%\Google\Chrome\User Data\Default\ |
| Edge (Chromium) | %LOCALAPPDATA%\Microsoft\Edge\User Data\Default\ |
| Brave | %LOCALAPPDATA%\BraveSoftware\Brave-Browser\User Data\Default\ |
| Firefox | %APPDATA%\Mozilla\Firefox\Profiles\<profile>\ |
| Opera | %APPDATA%\Opera Software\Opera Stable\ |
| Edge (UWP/Modern) | Traces also land in swapfile.sys. See the paging files comparison |
The interesting SQLite files in each Chromium-family profile:
Historyforurls,visits,keyword_search_terms,downloads.Cookiesfor name, value, host, expiry,encrypted_value(DPAPI-protected).Login Datafor theloginstable (saved passwords, DPAPI-encrypted).Web Dataforautofill,autofill_profile_*, credit cards (DPAPI-encrypted).
When these files are open in the live browser, their pages live in the renderer's process memory, and the decrypted form of cookies, autofill, and login data is in memory at use time. Both states can end up paged.
What the Artifacts tab catches
Drop a pagefile into the parser. The Artifacts tab extracts:
- URLs.
https?://[A-Za-z0-9\-._~:/?#\[\]@!$&'()*+,;=%]+over every extracted string. The full search-engine query string survives, includingq=.... - Emails. Common in autofill, account recovery flows, contact pages.
- IPv4 and IPv6. Useful when a query parameter or
X-Forwarded-Forcontained an address.
The Page map tags pages that started with SQLite format 3\0. Those are SQLite database pages, almost certainly from one of the browser DBs above.
The Strings tab is the catch-all:
- Filter for
Cookie:for HTTP cookie fragments. - Filter for
Set-Cookie:for server-issued cookies with their names, domains, paths. - Filter for
Authorization:for bearer tokens in API calls. - Filter for
user-agentto pivot between sessions or specific tab fingerprints. - Filter for
searchTerm,q=,query=for site-specific search history.
SQLite carving
When the Page map flags SQLite format 3 (a B-tree header page) or an interior B-tree page, you have a fragment of a browser DB. Pages are 4 KB by default (Chromium) or 32 KB (newer Firefox).
To extract structured records from a carved SQLite page:
- Use
sqlite_carvingorbring2lite. Both are purpose-built for SQLite record carving from raw memory. - Or open the bytes in
undarkorsqlite-deleted-recordsto read deleted rows.
Commonly extractable:
- URL + visit_time + title rows from
History.urlsandHistory.visits. Up to ~90 days of browsing in one page if you are lucky. - Cookie name / host / path / value rows from
Cookies. - Autofill key / value rows from
Web Data.autofill.
For Chromium DBs, the deleted-row recovery is the gold. A user "cleared their history" two hours before acquisition does not mean those rows are gone. They are marked free in the SQLite free-list and the page may have been paged out before the next vacuum.
Firefox vs Chromium
Firefox stores history in places.sqlite and bookmarks in the same DB. Schema is different but the carving approach is identical. Look for places.sqlite strings near SQLite pages, and for table names moz_places, moz_bookmarks, moz_historyvisits.
Firefox also stores session restore data in JSON files (sessionstore.jsonlz4). The on-disk form is LZ4-compressed but the decompressed content lives in memory and can page out as plain JSON. Filter for "entries": and "lastAccessed": to find them.
Edge IE-mode and Internet Explorer leftovers
If the host runs Edge in IE-mode (still common in enterprise), expect fragments of WebCacheV01.dat, the IE10+ ESE database. ESE pages have their own header layout (page header + tag array) and are not in the current default signature catalog. The strings inside them, host names, URLs, timestamps, will still surface in the Strings tab.
Operational tips
- Capture immediately. Every minute the browser runs, pages get rewritten. The longer you wait, the less you recover.
- Pair with the live profile. Carved pagefile data is more useful when you can diff it against the live SQLite. Anything in the pagefile that is not in the live DB is either a recently overwritten row, a deleted row, or InPrivate / Incognito traffic.
- Incognito and InPrivate are not safe from pagefile. The mode tells the browser not to persist to disk. RAM still holds the URLs and cookies, and the Memory Manager does not know which renderer is private. Incognito tabs show up.
- Cross-anchor URL hits with Prefetch for the browser process, LNK files, jump lists, and the USN journal for the download lifecycle. A naked URL is half a finding.
Further reading
- Chromium project, User Data Directory documentation for the canonical file layout.
- Maxim Suhanov, SQLite forensic blog posts on dfir.ru for deep coverage of free-list and unallocated-row recovery.
- Mozilla, Firefox profile data files reference for the equivalent on the Mozilla side.