---
id: personal-web-surfing-models/04-feasibility-of-a-personal-surfing-model-from
title: 'Personal web surfing models and an ought-driven tab feed: 4. Feasibility of
  a personal surfing model from browser history'
report: https://ai.hiina.space/reports/personal-web-surfing-models.md
section: 4
version: 1
updated: '2026-10-27'
author: Hiina
---

Index of everything on this site: https://ai.hiina.space/index.md

# Personal web surfing models and an ought-driven tab feed: 4. Feasibility of a personal surfing model from browser history

- Section 4 of 9 of the report "Personal web surfing models and an ought-driven tab feed" by Hiina (v1, updated 2026-10-27)
- Report overview and contents: https://ai.hiina.space/reports/personal-web-surfing-models.md
- Previous: https://ai.hiina.space/reports/personal-web-surfing-models/03-existing-web-surfing-models.md
- Next: https://ai.hiina.space/reports/personal-web-surfing-models/05-sharing-and-remixing-surfing-models.md

## 4. Feasibility of a personal surfing model from browser history

It is feasible, but not as a generative model trained on a URL stream. Build a local ranker on implicit labels, then add an LLM reranking pass against an editable profile and goals file. History records what a person did, distraction included, and the profile file is the cheapest place to write down what they should do.

### What the data actually holds

| Source                                                                                                                                                                                                   | Useful fields                                                                                                                                                            | Catch                                                                                            |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------|
| Chrome `History` SQLite: `urls`, `visits`                                                                                                                                                                | URL, title, visit time, `from_visit` referrer chain, transition type (link, typed, reload), `visit_duration` ([SANS](https://www.sans.org/blog/google-chrome-forensics)) | Reportedly keeps about 90 days by default (secondary source), so start archiving now             |
| Chrome `context_annotations`, `content_annotations`, `clusters` ([Chromium source](https://chromium.googlesource.com/chromium/src/+/HEAD/components/history/core/browser/visit_annotations_database.cc)) | Foreground duration, tab id, task tree (`root_task_id`, `parent_task_id`), page end reason, Chrome's own topic categories, entities, search terms and Journeys clusters  | Undocumented internal schema that can change                                                     |
| Firefox `moz_places_metadata` ([Interactions source](https://arai.searchfox.org/firefox-main/source/browser/components/places/Interactions.sys.mjs))                                                     | Per-visit view time, typing time, key presses, scroll distance, referrer                                                                                                 | The `browser.places.interactions.enabled` pref defaults to false, so past data probably lacks it |
| Session files: Firefox `recovery.jsonlz4` ([format](https://blog.dend.ro/decoding-firefox-session-store-data/)), Chrome SNSS ([crate](https://docs.rs/crate/snss/0.1.1))                                 | Open tabs per window, back-stack per tab                                                                                                                                 | Snapshot it periodically to get "kept vs closed" labels                                          |
| An extension using `chrome.tabs` ([docs](https://developer.chrome.com/docs/extensions/reference/api/tabs/))                                                                                              | Activation events (from which dwell can be computed), `lastAccessed`, `openerTabId`, groups, close events                                                                | Has to be written; `chrome.history` has no duration field                                        |

Existing plumbing to reuse: [Promnesia](https://beepb00p.xyz/exobrain/projects/promnesia.html) already merges browser databases and other sources into one local visits database. [ActivityWatch's web watcher](https://addons.mozilla.org/firefox/addon/aw-watcher-web/) logs the active tab locally. [ArchiveBox](https://docs.archivebox.io/v0.4.20/README.html) snapshots page content that can then be embedded. [Screenpipe](https://screenpipe.com/about) is local but source-available and needs a commercial license.

### Three modeling options at n=1

1.  **Fine-tune a small LM on visit sequences.** This is the weakest option. The nearest real result, [GoWeB](https://arxiv.org/pdf/2108.03350) (Microsoft Edge), used 57k users to reach next-page MRR@10 of about 0.11. One person's history is far smaller, and the model would mostly learn habits. Fine-tuning does pay once there are explicit preference labels: [TALLRec](https://arxiv.org/abs/2305.00447) adapted LLaMA-7B into a ranker with under 100 labeled pairs on a single 24 GB consumer GPU.

2.  **Embeddings plus a learned ranker.** This is the cheapest and easiest to debug. Embed title, URL and page text locally, then fit logistic regression or LightGBM on normalized dwell, revisits, bookmarks and tabs kept. The labels are noisy:

    - Raw dwell favors long pages and heavy readers, so normalize it per source and cap it ([ar5iv](https://ar5iv.labs.arxiv.org/html/2209.09000)).

    - Keeping a tab open often reflects fear of losing it, not importance (the CHI 2021 tab study in the tab triage section).

3.  **A frontier LLM with retrieval and a natural-language profile.** This is where the "ought" fits.

    - [Radlinski et al.](https://arxiv.org/abs/2205.09403v1) argue for editable, readable natural-language user profiles.

    - [Ramos et al.](https://arxiv.org/abs/2402.05810v2) (ACL 2024) found LLM-written profiles competitive with standard recommenders.

    - Short profiles of about 100 words held up for pairwise preference ([LFM](https://arxiv.org/pdf/2402.15623)).

    - Retrieving about 30 relevant past records beat dumping the full history ([LUNAR](https://arxiv.org/html/2608.05246v2)).

    - LLMs used as zero-shot rankers show position and popularity bias, which can be reduced by shuffling candidates and aggregating ([Hou et al.](https://arxiv.org/abs/2305.08845v2)).

### Evaluation

- Split strictly by time: train before date T and test after. Random splits leak the future ([Ji et al.](https://arxiv.org/abs/2010.11060v4)).

- Offline tasks: next-domain or next-cluster MRR, ranking tabs later reopened or bookmarked above tabs closed unread, and revisit prediction.

- Pairwise blind judgments in a small UI, which also produce fine-tuning data.

- Agent-in-the-loop: run the research agent with and without the ranker and rate the reports. Gwern's proposed metrics fit here: endorsement rate and regret per query.

- Score "is" and "ought" separately. A model that predicts someone's visits well may simply be predicting distraction.

### Privacy

- Browsing histories act like fingerprints. In a Mozilla study of about 52k users, 99% had unique histories ([Mozilla Foundation](https://www.mozillafoundation.org/en/research/library/why-we-still-cant-browse-in-peace-on-the-uniqueness-and-reidentifiability-of-web-browsing-histories/)). Hashing the URLs does not anonymize them.

- About 15% of a billion URLs tested carried special-category content such as health or politics ([IMDEA](https://networks.imdea.org/over-150-million-websites-among-a-billion-tested-include-sensitive-and-tracked-content/)).

- Keep raw history, embeddings and the ranker on a self-hosted machine. Send a hosted model only the reviewed profile plus candidate titles.

- Retention on hosted models: the Anthropic API deletes inputs within 30 days by default ([policy](https://privacy.claude.com/en/articles/7996866-how-long-does-anthropic-store-my-organizations-data)). Consumer plans keep data 5 years if the training setting is on ([terms update](https://www.anthropic.com/news/updates-to-our-consumer-terms)). Check that setting before piping history through a consumer-plan coding agent, or use a local Qwen model for the scoring pass.

---

Text licensed CC BY 4.0 (attribution: Hiina, ai.hiina.space). Source: https://github.com/hiinaspace/ai-hiina-space
