API Documentation
Search billions of leaked records programmatically — credentials, infostealer logs, ransomware leaks and data breaches. Every endpoint is a simple GET request that returns clean JSON.
https://haveibeenransom.com
Get started in 3 steps
New here? You can make your first call in under a minute. No SDK needed — just curl or any HTTP client.
Get your API token
Grab your personal token from your plan dashboard. It looks like a long random string and is yours alone — keep it secret.
Add the auth header
Send your token on every request inside the Authorization header, in the form Bearer YOUR_TOKEN.
Make your first request
Copy the example on the right, paste in your token, and run it. That's it — you'll get JSON back.
Your first request — copy, paste your token, run
curl -H "Authorization: Bearer YOUR_TOKEN" \ "https://haveibeenransom.com/api/metadata/email/[email protected]"
Authentication
Every request (except the public breach counters below) must include your API token. We use the standard Bearer token scheme: put your token in the Authorization header like this:
Authorization: Bearer YOUR_TOKEN
That's the only auth you need — no signatures, no OAuth dance. If the token is missing or wrong you'll get a 401 Unauthorized. Need a token? Pick a plan or email [email protected].
Keep your token private
Anyone with your token can spend your daily quota. Never commit it to public repos or ship it in front-end code. Send requests from your server, not the browser.
What can I search?
You search by field and term. The field tells us what kind of value you're looking for (an email, a domain, a wallet…) and the term is the value itself. Searches are case-insensitive and support partial matching.
You can also search multiple fields at once by separating them with commas — e.g. email,username. The two big datasets accept different fields:
Used by metadata, fulldata, fullransom and fullbreach. Great for checking which companies leaked a person's data.
Used by fullstealer. Includes crypto wallets, gaming accounts, Telegram and machine identifiers.
Field reference
| Field | What it matches | Datasets |
|---|---|---|
| name | Full names and name-related information | all |
| Email addresses | all | |
| username | Usernames and login identifiers | all |
| domain | Website domains / leaked email domains — returns every record tied to that domain | all |
| phone | Phone numbers and contact info | all |
| id | ID / document numbers (DNI, passport…) | all |
| country | Country (2-letter code, e.g. US, AU) | all |
| password | Passwords found in breaches / logs | all |
| wallets | Cryptocurrency wallet addresses | stealer |
| steamid | Steam account IDs | stealer |
| steamuser | Steam usernames | stealer |
| teleid | Telegram user IDs | stealer |
| teleuser | Telegram usernames | stealer |
| telephone | Telegram phone numbers | stealer |
| telelink | Telegram group links | stealer |
| vpn | VPN domains or IP addresses | stealer |
| ftp | FTP domains or IP addresses | stealer |
| hwid | Hardware / computer IDs | stealer |
Good to know
- Some fields map to several underlying columns so you get the widest possible match.
- Domain searches return all records associated with that domain.
- Combine fields with commas to widen a search:
email,username,name. - The
email_contextvalue attached to breach records bundles extra personal info (phone, name…) tied to that email.
Endpoint reference
Every endpoint is a GET request. Pick the one that matches what you need. The pattern is always /api/<endpoint>/<fields>/<term>.
Breach counters No auth
Two tiny public endpoints. Get the total number of breaches we track, or the full list of breaches sorted oldest-to-newest.
/breaches/total/breaches/fullExample request
curl "https://haveibeenransom.com/breaches/total"
Example response — /breaches/total
{
"total": 1113
}
Example response — /breaches/full
{
"breaches": [
{
"id": "11111",
"id_source": "11111",
"group_name": "ransomgang name",
"post_title": "Example Company Breached",
"post_url": "http://example3wh7hnmaiokchk7qoebupfgoik6rhaexample.onion/id=1234",
"website": "example.com",
"country": "US",
"description": "United States",
"discovered": "2024-12-16 21:07:57.040833",
"indexed": "2025-07-11T00:33:13.072665",
"Identities Found": 1872
}
]
}
1 · Metadata search
Which breaches affected this person/domain? Returns lightweight breach metadata (company, group, date, country) without exposing the sensitive records. Results are paginated, 20 per page.
/api/metadata/<fields>/<term>/api/metadata/<fields>/<term>/<page>/api/metadata/<fields>/<term>/completeEnterpriseParameters
| Param | Meaning | Example |
|---|---|---|
| fields | required · what to match: name, phone, email, username, id, country, domain, password | |
| term | required · the value to search | [email protected] |
| page | optional · page number (default 1) | 2 |
Example — single field
curl -H "Authorization: Bearer YOUR_TOKEN" \ "https://haveibeenransom.com/api/metadata/domain/example.com"
Example — multiple fields
curl -H "Authorization: Bearer YOUR_TOKEN" \ "https://haveibeenransom.com/api/metadata/email,username/[email protected]"
Example response
{
"success": true,
"results": [
{
"Identities Found": 1872,
"country": "US",
"description": "United States",
"discovered": "2024-12-16 21:07:57.040833",
"group_name": "ransomgang name",
"id": "11111",
"id_source": "11111",
"indexed": "2025-07-11T00:33:13.072665",
"post_title": "Example Company Breached",
"post_url": "http://example3wh7hnmaiokchk7qoebupfgoik6rhaexample.onion/id=1234",
"website": "example.com"
}
],
"pagination": {
"current_page": 1,
"total_pages": 3,
"total_sources": 45,
"has_next": true,
"has_previous": false
}
}
2 · Full data search
The actual records, not just metadata. Same shape across three sibling endpoints — pick one depending on which dataset you want to search:
| Endpoint | Searches |
|---|---|
| /api/fulldata | Everything combined — ransomware leaks + traditional breaches + ULP/combolists |
| /api/fullransom | Ransomware leaks only |
| /api/fullbreach | Traditional data breaches only |
/api/fulldata/<fields>/<term>/api/fulldata/<fields>/<term>/<id_source>/api/fulldata/<fields>/<term>/completeEnterprise/api/fullransom/… and /api/fullbreach/… accept the exact same path variants.
Parameters
| Param | Meaning | Example |
|---|---|---|
| fields | required · email, name, phone, username, id, country, domain, password | domain |
| term | required · the value to search | example.com |
| search_after | optional query param · cursor for the next page (default 0) | ?search_after=253941 |
| id_source | optional · restrict results to one breach source | 11111 |
Paid plans only
Full data endpoints require a paid data plan. Requests from a Basic token get a 403 asking you to upgrade.
Example — single field
curl -H "Authorization: Bearer YOUR_TOKEN" \ "https://haveibeenransom.com/api/fulldata/domain/example.com"
Example — next page (cursor pagination)
curl -H "Authorization: Bearer YOUR_TOKEN" \ "https://haveibeenransom.com/api/fulldata/email/[email protected]?search_after=253941"
Example response
{
"success": true,
"email": "[email protected]",
"data": [
{
"email": "[email protected]",
"email_context": "phone, name, etc",
"From archive": "This domain has been in PDF archive example.pdf",
"source_metadata": {
"country": "US",
"description": "Lorem ipsum......",
"group_name": "play",
"company_affected": "Company XYZ",
"post_url": "http://example3wh7hnmaiokchk7qoebupfgoik6rhaexample.onion/id=1234",
"website": "example.com"
}
}
],
"has_next_page": true,
"search_after": 253941,
"total_hits": 325478
}
To page through results, take search_after from the response and pass it back as ?search_after=.... When has_next_page is false, you've reached the end.
3 · Full stealer search Infostealer logs
Stolen credentials, crypto wallets, gaming accounts, Telegram and more — straight from infected machines. This is the richest dataset, so its response can take three different shapes. Read the top-level "mode" first.
/api/fullstealer/<fields>/<term>/api/fullstealer/<fields>/<term>?search_after=X/api/fullstealer/<fields>/<term>/completeEnterpriseParameters
| Param | Meaning | Example |
|---|---|---|
| fields | required · any infostealer field (email, username, wallets, steamid, teleuser, vpn, country…) | |
| term | required · the value to search (country must be a 2-letter code) | [email protected] |
| search_after | optional query param · cursor for the next page (default 0) | ?search_after=2587 |
First, how infostealer data is organized
When a machine is infected, the stealer dumps everything into 5 buckets (indexes):
Credential→ saved logins (URL / user / password)Cookies→ browser cookies / sessionsInfo→ system info (Country, OS, HWID, log date…)plus→ extras: crypto wallets, VPN, FTP, Steam, Telegram…Filelist→ list of files grabbed from the machine
Every document shares the same Filename — a unique ID for the infected machine, e.g. HWID E32F8AFB9CF347BA22FCCF354C9E9B5C_analysis14951. Think of Filename as the "victim machine ID" that glues all the pieces together.
The response has 3 shapes — always check "mode"
The field you search by decides the shape. Read the top-level "mode" value and parse accordingly:
| mode | When you search by… | What you get |
|---|---|---|
| fragments | email, username, phone, id, domain, password | A flat list in "matches", one item per credential: {URL, USER, PASS, Filename}. |
| documents | wallets, steamid, steamuser, teleid, teleuser, telephone, telelink, vpn, ftp, hwid | Raw documents in "data", each as {_index, _source}. |
| stealers | country | Results grouped per infected machine in "data" — every document from all 5 indexes bundled together. |
Example — by email (mode: fragments)
curl -H "Authorization: Bearer YOUR_TOKEN" \ "https://haveibeenransom.com/api/fullstealer/email/[email protected]"
Example — by country (mode: stealers)
curl -H "Authorization: Bearer YOUR_TOKEN" \ "https://haveibeenransom.com/api/fullstealer/country/AU"
Response A — mode: "fragments"
When you search by email, username, phone, id, domain or password. Each item in matches is one matching login; Filename tells you which machine it came from.
{
"mode": "fragments",
"matches": [
{
"URL": "https://login.example.com",
"USER": "[email protected]",
"PASS": "leaked_password_123",
"Filename": "HWID E32F8AFB9CF347BA22FCCF354C9E9B5C_analysis14951"
}
],
"count": 1,
"total_docs": 14356,
"search_term": "example.com",
"fields": ["domain"],
"search_after": 2587,
"has_next_page": true
}
Response B — mode: "documents"
When you search by wallets, steamid, steamuser, Telegram fields, vpn, ftp or hwid. Each entry in data is a raw document; the real content lives in _source, and _index tells you which bucket it came from.
{
"mode": "documents",
"data": [
{
"_id": "kJ3l9ZcBxq",
"_index": "logs_plus",
"_score": null,
"_source": {
"Filename": "HWID E32F8AFB9CF347BA22FCCF354C9E9B5C_analysis14951",
"HWID": "E32F8AFB9CF347BA22FCCF354C9E9B5C",
"Country": "AU",
"Wallets Cracked": ["bc1qxy2k...", "0x1283921ASDK..."]
}
}
],
"count": 1,
"total_hits": 320,
"search_term": "76561198012345678",
"fields": ["steamid"],
"has_next_page": false
}
Response C — mode: "stealers" (country search)
Only when you search by country. data is a list of infected machines. Each machine has its filename, a count of its documents, and a documents array bundling everything found for that machine across the 5 indexes.
{
"mode": "stealers",
"data": [
{
"filename": "HWID E32F8AFB9CF347BA22FCCF354C9E9B5C_analysis14951",
"count": 4,
"documents": [
{
"_index": "logs_info",
"_source": {
"Filename": "HWID E32F8AFB...analysis14951",
"Country": "AU",
"HWID": "E32F8AFB9CF347BA22FCCF354C9E9B5C",
"LogDate": "2024-11-02"
}
},
{
"_index": "logs_credential",
"_source": {
"Filename": "HWID E32F8AFB...analysis14951",
"Credentials": [
{
"URL": "https://mail.example.com",
"USER": "[email protected]",
"PASS": "hunter2"
}
]
}
},
{
"_index": "logs_plus",
"_source": {
"Filename": "HWID E32F8AFB...analysis14951",
"Wallets Cracked": ["bc1qxy2k...", "0x9aF3..."],
"VPN info": "nordvpn.com"
}
},
{
"_index": "logs_filelist",
"_source": {
"Filename": "HWID E32F8AFB...analysis14951",
"Files": ["C:\\Users\\victim\\Desktop\\passwords.txt"]
}
}
]
}
],
"count": 1,
"total_hits": 5821,
"search_term": "AU",
"fields": ["country"],
"search_after": 1024,
"has_next_page": true
}
How to read it
count(top level) → machines returned on this page.total_hits→ total country matches across all pages.data[].count→ how many documents that single machine has.- Use
search_after+has_next_pageto page through more machines.
4 · Leak analytics
Profile a single breach. Give it a breach's id_source and get aggregated analytics: corporate vs personal email split, how many identity documents, a file-type breakdown, and the breach's metadata.
/api/fullmetadata/<id_source>Parameters
| Param | Meaning | Example |
|---|---|---|
| id_source | required · the breach source ID (from a metadata or breaches result) | 11111 |
Example request
curl -H "Authorization: Bearer YOUR_TOKEN" \ "https://haveibeenransom.com/api/fullmetadata/11111"
Example response
{
"id_source": "11111",
"leak_type": "ransomware_leak",
"total_records": 1872,
"breach_metadata": {
"post_title": "Example Company Breached",
"group_name": "play",
"country": "US",
"discovered": "2024-12-16 21:07:57.040833"
},
"email_origin": {
"total_emails": 1500,
"records_with_email": 1450,
"internal_corporate": { "count": 900, "percentage": 60.0 },
"external_personal": { "count": 600, "percentage": 40.0 }
},
"identity_documents": {
"count": 120,
"percentage_of_records": 6.41
},
"file_types": {
"distinct_types_present": 4,
"breakdown": {
"pdf": 150,
"csv": 80,
"xlsx": 30,
"databases": 200
}
}
}
5 · Domain overview Enterprise
One call, full picture of a domain's exposure. Runs infostealer (clients & employees), breaches and ransomware lookups in parallel and returns the totals plus top URLs and users. Non-Enterprise tokens receive a safe demo response with "is_demo": true.
/api/domain_overview/<domain>Parameters
| Param | Meaning | Example |
|---|---|---|
| domain | required · the domain to profile (use example.* to match all TLDs) | example.com |
Example request
curl -H "Authorization: Bearer YOUR_TOKEN" \ "https://haveibeenransom.com/api/domain_overview/example.com"
Example response (trimmed)
{
"domain": "example.com",
"exposures": {
"infostealer": {
"clients": {
"total_exposures": 1820,
"unique_urls": 45,
"urls": [{ "url": "https://login.example.com", "count": 320 }],
"users": [{ "user": "[email protected]", "count": 12 }],
"status": "success"
},
"employees": {
"total_exposures": 230,
"unique_urls": 8,
"urls": [],
"users": [{ "user": "[email protected]", "count": 3 }],
"status": "success"
},
"total": 2050
},
"breaches": {
"count": 540,
"unique_sources": 6,
"sources": [
{ "source_id": "abc123", "count": 320, "metadata": { "name": "Acme DB" } }
],
"status": "success"
},
"ransomware": {
"count": 1872,
"unique_sources": 3,
"sources": [
{ "source_id": "11111", "count": 1872, "metadata": { "name": "play" } }
],
"status": "success"
}
},
"total_exposures": 4462,
"execution_time_seconds": 1.234,
"timestamp": 1735000000.0
}
6 · Usage stats
See how the API is being used. Get your own token's daily usage, or the global, anonymized stats. Both accept optional ?date=YYYY-MM-DD and ?days=N query params.
/api/<token>/stats/api/general/statsParameters
| Param | Meaning | Example |
|---|---|---|
| token | required (per-token route only) · your API token, in the path | YOUR_TOKEN |
| date | optional query param · day to report (default today) | ?date=2026-06-26 |
| days | optional query param · how many days back to aggregate (default 1) | ?days=7 |
Example request
curl "https://haveibeenransom.com/api/YOUR_TOKEN/stats?days=7"
Example response — per token
{
"date": "2026-06-26",
"token": "abc12345...",
"statistics": {
"total_queries": 42,
"by_field": { "email": 30, "domain": 12 },
"by_query_type": { "metadata": 18, "fulldata": 24 },
"unique_terms": ["[email protected]", "example.com"],
"hourly_distribution": { "9": 10, "14": 32 }
}
}
Complete mode
Add /complete to the end of a metadata, fulldata, fullransom, fullbreach or fullstealer request to get every result at once, with no pagination.
Enterprise only
Because /complete can return enormous datasets, it's reserved for Enterprise license holders. Other plans get a 403 telling them to upgrade. Everyone else should page normally with page (metadata) or search_after (fulldata / fullstealer).
curl -H "Authorization: Bearer YOUR_TOKEN" \ "https://haveibeenransom.com/api/fulldata/email/[email protected]/complete"
Rate limits
Each plan includes a daily API quota (requests per day). Every response carries rate-limit headers so you can track your usage. Go over the limit and you'll get a 429 Too Many Requests until the next reset.
| Plan | API requests / day | Complete mode |
|---|---|---|
| Basic | 100 | — |
| Professional | 2,000 | — |
| Cybersecurity Agency | 20,000 | — |
| Enterprise / Gov | Unlimited | Included |
Error responses
The API uses standard HTTP status codes. When something goes wrong you get a JSON body explaining it. Here's what each code means and what to do:
| Code | Meaning | What to do |
|---|---|---|
| 400 | Bad request — invalid parameters (bad field, empty term, malformed email or country code) | Check your field name, term and format, then retry. |
| 401 | Unauthorized — missing or invalid token | Confirm your Authorization: Bearer header and token. |
| 403 | Forbidden — your plan doesn't include this feature (e.g. full data, or /complete) | Upgrade your plan to unlock it. |
| 429 | Too many requests — daily rate limit exceeded | Wait for the daily reset or upgrade for a higher quota. |
| 500 | Internal server error | Retry shortly; if it persists, contact support. |
Example error body
{
"success": false,
"error": {
"code": 403,
"message": "Enterprise feature required",
"details": "The /complete endpoint is only available for Enterprise license holders"
}
}
Frequently asked questions
QWhat's the difference between metadata and full data search?
Metadata search returns basic breach information (which companies, groups and dates) without sensitive details. Full data search returns the comprehensive records about the specific data that was compromised.
QWhat's the difference between fulldata and fullstealer?
fulldata searches ransomware breach and traditional breach data. fullstealer searches infostealer logs — stolen credentials, crypto wallets, gaming accounts and other sensitive data pulled from infected machines.
QHow often is the database updated?
Continuously, as new ransomware breaches and infostealer logs are discovered and verified. Updates typically land within 24–48 hours of breach disclosure.
QCan I search for domains instead of specific emails?
Yes. All endpoints support domain queries (e.g. example.com) to find every breach or log affecting that domain.
QWhat is Complete mode and how do I access it?
Complete mode returns all results without pagination — handy for full exports. It's exclusive to Enterprise license holders. Email [email protected] to upgrade.
QHow does pagination work?
Metadata search uses page numbers (up to 20 per page). fulldata and fullstealer use cursor-based pagination via search_after (20 per request). Take the search_after value from the response and pass it as a query parameter for the next batch: ?search_after=2587. When has_next_page is false, you've reached the end.
QWhy does a country search on fullstealer look different?
A country search returns "mode": "stealers" — results grouped per infected machine. Instead of one isolated row, each machine comes with all of its documents (credentials, cookies, system info, wallets, file list) bundled under its Filename. That gives you the complete profile of every victim machine in that country in one call. All other fields keep their fragments / documents shapes.
QHow do I know which response shape to expect from fullstealer?
Always read the top-level "mode" field. fragments → look in matches (flat list of {URL, USER, PASS, Filename}). documents → look in data (raw docs, real content inside _source). stealers → look in data (one entry per machine, documents bundled inside).
Ready to start building?
Pick a plan to get your API token, or reach out and we'll help you choose.