"Something is broken" tickets are useless without the details: what the console said, what browser they used, what the screen looked like. Here is how to collect all of it with one script tag — even on a site with no server at all.
Updated August 2026 · 6 minute read
A typical feedback form asks the user to describe the problem in words. Most don't. They can't see the console, they don't know their viewport size, and writing out steps takes effort. The result: you hear about maybe one in fifty real problems, each with just enough detail to be unusable.
The actual stack trace is already sitting in the user's browser. Capturing it removes the single hardest part of debugging remotely.
User agent, viewport, language, timestamp, page URL. Collected automatically instead of guessed over email.
One picture replaces ten back-and-forth messages about "the thing that looks weird".
Bugbottle is an open-source (MIT) JavaScript library that does exactly this. Drop it on any page:
<script type="module">
import {
initConsoleBuffer, getConsoleBuffer,
collectContext, captureScreenshot
} from 'https://cdn.jsdelivr.net/npm/bugbottle/dist/index.js';
initConsoleBuffer(); // start capturing console errors now
document.getElementById('report-btn').addEventListener('click', async () => {
let screenshotDataUrl;
if (document.getElementById('include-shot').checked) {
screenshotDataUrl = await captureScreenshot();
}
const res = await fetch('/api/bug-reports', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
message: 'User clicked report',
screenshotDataUrl,
console: getConsoleBuffer(),
context: collectContext(),
})
});
});
</script>
The library is dependency-free and ships as plain ESM, so it works straight from jsDelivr — no bundler, no npm install for your visitors, nothing to compile.
You have three realistic options, all of them free at hobby scale:
Cloudflare Workers, Vercel functions or Netlify functions accept a POST and store the JSON anywhere — KV, R2, a database table. Bugbottle ships a matching server-side validator (bugbottle/server) so you reject malformed payloads in three lines.
Any endpoint that accepts JSON POSTs can receive a report — Formspree, Basin, or your own Google Apps Script web app. Validate before storing.
The bugbottle-action validates collected reports inside CI — useful when reports are exported as files in your repo.
See it working end to end: the live bugbottle demo runs the real library from jsDelivr against a real endpoint. Submit a report, then watch it arrive with type, message, console entries and context attached.
Bug reports are personal data under GDPR the moment they can identify someone. Keep the footprint small:
Collect: error messages, stack traces, page URL, viewport size, browser family, language.
Skip by default: IP addresses, cookies, form contents, full DOM snapshots. If you screenshot, remember the visible screen may contain the user's own data — let them preview and delete before sending.
Mention the collection in your privacy policy under the same section as analytics. It is one sentence: "Users may submit voluntary error reports containing technical diagnostics."
Yes — anything where you can add a custom HTML block or edit the footer template. The library is platform-agnostic plain ESM.
A few kilobytes minified, zero dependencies. It loads lazily when the report button is used, not on page load.
No — only when the user actively submits a report, and you choose whether to request one. Nothing is captured passively.
Yes. MIT licensed, host the dist files yourself and point the import at your own CDN if you don't want third-party requests.