DEV Community

Cover image for My Browser History Wrote Its Own Horror Story. I Just Watched.
Malay-dev
Malay-dev

Posted on Edited on AI-assisted

My Browser History Wrote Its Own Horror Story. I Just Watched.

Hacktoberfest Open-Source AI Challenge: Ghost in the Machine Submission πŸ‘»πŸŒΌ

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine

What I Built

It's 2am. You're on Stack Overflow. Again. For the seventh time this week. You know how to reverse a string. You've known for years. You just need to hear it from a stranger who asked in 2009.

Nobody sees your browser history. But what if something did β€” and narrated it back to you like a Victorian ghost story?

Browser History Horror reads your Chrome history, detects your most unhinged browsing sessions using anomaly detection, and feeds them to Gemma running locally. Gemma writes it back as gothic horror. ElevenLabs reads it aloud in a creepy voice. You sit there and take it.

Your history never leaves your machine. The AI that judges you lives on your laptop.

The Archivist Speaks

This is real output from my actual browsing history. I wish I was making this up.

It began on Monday at 23:47. A single search β€” innocent enough on its face.
The developer already possessed this knowledge. They had possessed it for
years. Yet here they were, returning to the eternal repository of unanswered
questions, seeking the validation of strangers who had asked the same thing
in 2009.

They left. They returned. They left again. Eight times between 23:47 and
00:31, the same domain welcomed them back with the patience of a very old
spider.

The orange forum came next β€” a brief interlude, a glance at the horrors
others had inflicted upon their codebases. Reassuring in its way. At least
they were not that.

At 01:15, something shifted. The work-adjacent sites fell away. What replaced
them was a video labyrinth, vast and illuminated, designed by engineers who
understood that the human soul has no natural stopping point.

The last entry: 01:44. A search that shall remain unrecorded. The browser
was closed, and the darkness of the room was left to do what darkness does.

Tomorrow was Tuesday. It had already begun.
Enter fullscreen mode Exit fullscreen mode

Stack Overflow is "the eternal repository of unanswered questions." Reddit is "the orange forum." YouTube is "the video labyrinth." LinkedIn is "the professional purgatory."

Gemma never uses real URLs. It gives every site a gothic alias and writes about your habits like a disappointed Victorian ghost.

How It Works

Browser SQLite ──► History Reader ──► Anomaly Detector ──► Gemma Narrator ──► Gothic UI
     (local)         (pandas)        (TabPFN/heuristic)    (Ollama local)    (FastAPI + SSE)
Enter fullscreen mode Exit fullscreen mode

Step 1: Summon Your History

Chrome stores everything in a SQLite file. The tool copies it to temp (bypasses the browser lock), extracts the last 7 days, and engineers features β€” hour of visit, domain frequency, session gaps, rapid revisits.

  πŸ“– History found: ~/Library/Application Support/Google/Chrome/Default/History
  1,395 rows extracted in 0.1s
  1,215 marked as heuristically haunted
Enter fullscreen mode Exit fullscreen mode

87% of my browsing is "heuristically haunted." I don't want to talk about it.

Step 2: Detect the Hauntings

The heuristic rules catch the obvious sins:

  • Visits between midnight and 4am
  • 5+ visits to the same domain within 30 minutes
  • Rapid-fire revisits (< 30 seconds apart)
  • Unknown domains after 10pm

TabPFN (tabular foundation model from Prior Labs) refines this β€” it picks up subtler patterns like a slow drift from work tools β†’ entertainment β†’ doom-scrolling that only looks haunted in context. If TabPFN isn't available, heuristic scoring works fine on its own.

3 chapters extracted:
  Saturday, Oct 24  | 16:09 | MALEVOLENT (1.00) | claude.ai
  Sunday, Oct 25    | 07:09–17:37 | MALEVOLENT (1.00) | gitlab, google
  Monday, Oct 26    | 04:16–15:12 | MALEVOLENT (1.00) | jira, google, docs
Enter fullscreen mode Exit fullscreen mode

Every single session: MALEVOLENT. The algorithm is not wrong.

Step 3: The Archivist Writes

Gemma 3 4B runs locally via Ollama. Each chapter gets a system prompt that enforces the gothic voice:

  • Second person ("the developer", "they") β€” never breaks character
  • Sites become gothic aliases β€” never raw URLs
  • One darkly comic observation per chapter
  • One ominous closing line

The prompt also includes visit patterns, timestamps, and intensity scores so Gemma can reference your actual behavior without ever seeing the raw data.

Step 4: The SΓ©ance

A gothic web UI streams everything in real time:

  • Flickering candle SVGs in the header
  • Chapters stream in with a typewriter effect as Gemma generates them
  • Each chapter shows a Haunting Intensity bar powered by the anomaly score
  • ElevenLabs reads each chapter aloud in a measured, deliberate voice
  • A fog layer drifts at the bottom of the page because atmosphere matters
  • When it's over, download your Grimoire β€” a self-contained HTML file of your sins

No React. No build step. One HTML file with vanilla JS. The sΓ©ance needs no bundler.

The Privacy Argument

This is the slide I'd put in a conference talk if I gave conference talks:

Data Where it goes
Browser history Copied to temp, queried, deleted. Never leaves your machine.
Feature vectors Processed locally by TabPFN. Never sent anywhere.
Narration prompts Sent to local Ollama. Never touches a cloud API.
Generated prose Sent to ElevenLabs for TTS β€” only the gothic text, not your history.
Sentry traces Latency numbers and model names only. No content.

Your browser history is a confessional. The only AI that should read it is one that lives on your hardware and can't phone home. Gemma running locally via Ollama is the only appropriate choice here. A cloud API would mean shipping your 2am Stack Overflow spiral to someone else's server. No.

Run It Yourself

# Prerequisites: Python 3.11+, Ollama running
ollama pull gemma3:4b

git clone https://github.com/Malay-dev/browser-history-horror.git
cd browser-history-horror
pip install -r requirements.txt
python seance.py
Enter fullscreen mode Exit fullscreen mode

Browser opens. Click the button. Face your sins. Three commands.

ElevenLabs is optional β€” without an API key, the browser's built-in speech synthesis does the reading (less creepy, still functional). Sentry tracing is optional too. The core experience is Gemma + your history + guilt.

Code

πŸ•―οΈ Browser History Horror

"On Tuesday at 2am, the developer returned to Stack Overflow for the seventh time They searched for 'how to center a div.' They knew the answer. They just needed to hear it again."

A fully local, privacy-first tool that reads your browser history, detects anomalous browsing patterns, and narrates your week as a gothic horror story β€” complete with creepy voice narration and a downloadable "grimoire" of your sins.

Your browsing history never leaves your machine during analysis. The only data that touches an external service is the generated narration text sent to ElevenLabs for text-to-speech (and that's optional).

Built for the Hacktoberfest 2026 Ghost in the Machine challenge.


How It Works

Browser SQLite ──► History Reader ──► Anomaly Detector ──► Gemma Narrator ──► Gothic UI
     (local)         (pandas)          (TabPFN/heuristic)    (Ollama local)    (FastAPI + SSE)
  1. Extract β€” Copies your Chrome/Chromium/Brave/Edge history from SQLite (bypasses the browser lock)
  2. …

browser-history-horror/
β”œβ”€β”€ seance.py              # Entry point β€” checks Ollama, finds history, starts server
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ history.py         # SQLite reader + feature engineering (8 features)
β”‚   β”œβ”€β”€ detector.py        # TabPFN scoring + session grouping
β”‚   β”œβ”€β”€ narrator.py        # Gothic prompt design + Ollama streaming
β”‚   β”œβ”€β”€ tts.py             # ElevenLabs with speechSynthesis fallback
β”‚   β”œβ”€β”€ api.py             # FastAPI + SSE streaming + grimoire generation
β”‚   └── tracer.py          # Sentry span instrumentation
β”œβ”€β”€ frontend/
β”‚   └── index.html         # Self-contained gothic UI (19KB, zero deps)
└── requirements.txt
Enter fullscreen mode Exit fullscreen mode

How I Built It

Gemma 3 4B via Ollama β€” local inference, streaming. The system prompt is doing the heavy lifting β€” it enforces the gothic voice, prevents URL leakage, and structures each chapter with a comic beat and an ominous closer. Domain aliasing happens post-generation as a safety net: even if Gemma slips, sanitize_narration() catches raw domains and replaces them.

TabPFN β€” in-context tabular classification. No train/test split needed. The heuristic seed labels ("obviously haunted" by simple rules) become training signal, and TabPFN picks up cross-feature interactions. The fallback to heuristic-only scoring means the tool works even without the gated model weights.

FastAPI + SSE β€” the narrator streams chunks as Gemma generates them. The browser consumes Server-Sent Events and renders text character by character. No WebSocket complexity, no polling. TTS audio is generated async and served via a separate endpoint when ready.

ElevenLabs β€” eleven_turbo_v2_5 for low latency. The free tier gives 10,000 characters/month β€” enough for one full sΓ©ance (~7,500 chars across 5 chapters). Falls back to the Web Speech API with pitch dropped to 0.75 for a budget-gothic effect.

Sentry β€” every pipeline stage is a span: history extraction, feature engineering, TabPFN scoring, each Gemma chapter, each ElevenLabs call. The trace waterfall shows exactly where the time goes (spoiler: it's Gemma, always Gemma).

Frontend β€” one HTML file. CSS custom properties for the color palette. SVG candles with randomized flicker animations. Typewriter effect via JS chunked rendering. The haunting intensity bar is a CSS gradient driven by the anomaly score. The grimoire download generates a self-contained HTML file server-side.

Why Does Open Innovation Matter?

Browser history is the most personal dataset on your computer. Every anxious 2am search, every rabbit hole, every time you Googled something you already knew β€” it's all there in plain SQLite.

The only way to build something like this responsibly is with open-weight models running locally. Gemma on Ollama means the model that reads your history lives on your hardware. No API keys for the scary part. No telemetry. No "we improved our model using your data."

Open-source also means you can read exactly what data goes where. The privacy model isn't a policy document β€” it's six Python files you can audit in 10 minutes.

I built a tool that reads your most private data and turns it into entertainment. If that doesn't make the case for local AI, I don't know what does.

The Gothic Payoff

Before: Browser history is a log file you never look at.

After: Browser history is a horror story you can't stop reading.

I ran this on my own history and learned that I visited claude.ai 9 times in one sitting on a Saturday afternoon. The Archivist called it "a peculiar fixation" and "a futile endeavour mirroring the human condition itself."

It's not wrong. Ship it. Face your sins.

Prize Categories

Gemma β€” Core narrative engine. Local inference via Ollama, streaming generation, gothic system prompt with domain aliasing and output sanitization. Every word of the horror story is Gemma. #Gemma

TabPFN β€” Anomaly detection on browsing session features. In-context classification on 8 engineered features with heuristic seed labels. Surfaces the sessions that become chapters. #TabPFN

ElevenLabs β€” Chapter narration voiced in-browser. Turbo v2.5 for low latency, with Web Speech API fallback. Only receives generated prose, never raw history. #ElevenLabs

Sentry β€” Full pipeline traced with spans. History extraction β†’ feature engineering β†’ TabPFN scoring β†’ per-chapter Gemma generation β†’ per-chapter TTS. Latency, token counts, audio sizes β€” all in one trace waterfall. #Sentry

Render β€” Gothic web UI deployed as a static site for the public demo. Anonymized fixture data so visitors can experience the sΓ©ance without exposing their own history. #Render

Top comments (0)