A lightweight web app for checking emails and passwords against the Have I Been Pwned database. Runs locally or deploys to Vercel in one command.
- Email breach lookup — check one or more emails against all known breaches
- Paste site lookup — check if emails appear on Pastebin and similar sites
- Password check — hashed in your browser and checked with k-anonymity (only a 5-character hash prefix is sent; your password never leaves your browser)
- Browser-side API key — users paste their own HIBP key; it's stored in
localStorageand never hardcoded - Export results — download breach and paste results as JSON, CSV, or PDF
- Rate limit handling — emails are checked one at a time with live progress; if HIBP rate-limits a lookup, the app waits for the
retry-afterperiod and retries automatically
The HIBP basic plan allows 10 email lookups per minute. Emails are checked one at a time and results appear as they arrive. If HIBP returns a rate-limit response, the app waits for the period HIBP specifies and retries (up to 3 times per email), so large lists just take longer instead of failing. Higher-tier plans have increased limits — see HIBP pricing for details.
- Node.js v18+
- A HIBP API key (required for email lookups; password checks are free)
git clone https://github.com/denniskeefe/hibp-app.git
cd hibp-app
npm install
node server.jsOpen http://localhost:3737, paste your API key into the banner, and start checking.
npm i -g vercel
vercelNo extra configuration needed — vercel.json is already set up. Each user enters their own API key in the browser; nothing is stored server-side.
api/
_hibp.js # Shared fetch logic and helpers
breaches.js # POST /api/breaches — breach lookup for one email
pastes.js # POST /api/pastes — paste lookup for one email
public/
index.html # Single-page frontend (no build step)
app.js # Frontend logic, including the in-browser password check
server.js # Local dev Express server (delegates to /api/ handlers)
vercel.json # Vercel routing and security headers (also applied by server.js)
- The HIBP API key is stored in your browser's
localStorageand sent as anx-hibp-keyrequest header — it is never embedded in source code - Password checks run entirely in the browser using the k-anonymity model: the password is SHA-1 hashed locally and only the first 5 characters of the hash are sent directly to the Pwned Passwords API (with response padding enabled). The password is never sent to this app's server
- All data returned by HIBP is HTML-escaped before rendering, and a strict Content-Security-Policy restricts scripts to this site and the pinned jsPDF build (loaded with Subresource Integrity only when exporting a PDF)
- If self-hosting for others, consider adding authentication in front of the app to prevent unauthorized use of your API key