Email Lookup &
Username Search API.
Integrate email lookup, username search, breach detection, and OSINT enrichment into your applications through a single REST API — built for security, fraud-prevention, and authorized investigation teams.
API responses are fetched live, in real time, at request time from publicly available sources and endpoints; Revealer.US does not own that data and does not retain your search data. Revealer.US is not a consumer reporting agency. API results may not be used for any FCRA-covered purpose, including employment, credit, tenant screening, or insurance eligibility. See our Terms of Service.
On this page
Quick start
- 1
Get API Key
API access is included on Pro and above with 500 API requests per week. Need higher API volume or team seats? Talk to sales about Enterprise.
- 2
Make Request
Send authenticated REST requests
- 3
Get Results
Receive structured JSON responses
Authentication
Include your API key in the Authorization header:
Authorization: Bearer sk_live_your_api_keySecurity: Never expose your API key in client-side code. Make API calls from your backend.
Code examples
import json
import requests
API_KEY = "sk_live_..."
BASE_URL = "https://revealer.us"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
# Verify your API key first
def verify_api_key():
response = requests.get(f"{BASE_URL}/api/v1/verify", headers=headers)
return response.json()
# Resolve a username/handle
# /api/resolve answers with Server-Sent Events, not a single JSON body:
# read the "data: " frames and keep the final {"type": "complete"} one.
def resolve_handle(handle):
with requests.post(
f"{BASE_URL}/api/resolve",
headers={**headers, "Accept": "text/event-stream"},
json={"handle": handle},
stream=True
) as response:
for line in response.iter_lines(decode_unicode=True):
if not line or not line.startswith("data: "):
continue
frame = json.loads(line[6:])
if frame.get("type") == "complete":
return frame.get("data")
return None
# Search breach records
def search_breaches(search_type, term):
response = requests.post(
f"{BASE_URL}/api/database/search",
headers=headers,
json={"type": search_type, "term": term}
)
return response.json()
# Search stealer logs (Pro and above — 50/day on Pro; each API call counts against your weekly API budget)
def search_stealer_logs(search_type, term, limit=35):
response = requests.post(
f"{BASE_URL}/api/stealer-logs/search",
headers=headers,
json={"type": search_type, "term": term, "limit": limit}
)
return response.json()
# Example usage
result = search_breaches("email", "[email protected]")
if result.get("success"):
print(f"Found {result['data']['found']} records")Endpoints
14 endpointsGET/api/v1/infoPublicGet API information, available endpoints, and your detected IP address (no auth required)
Response
{
"success": true,
"api": { "version": "1.0", "status": "operational" },
"client": { "ip": "1.2.3.4", "user_agent": "..." },
"authentication": { "method": "Bearer Token", "header": "Authorization" },
"endpoints": { "public": {...}, "authenticated": {...} },
"rate_limits": { "requests_per_second": 1, "api_requests_per_week": 500, "period": "ISO week (Monday 00:00 UTC)" }
}GET/api/v1/verifyProVerify API key is working and check your access level
Response
{
"success": true,
"authenticated": true,
"auth_method": "api_key",
"user": { "email": "[email protected]", "tier": "PREMIUM" },
"limits": {
"social_searches_per_period": 500,
"breach_searches_per_period": "unlimited",
"quota_period": "day",
"requests_per_second": 1,
"api_access": true,
"api_requests_per_week": 500,
"max_whitelisted_ips": 3
},
"api_usage": { "used": 12, "remaining": 488, "limit": 500, "resets_at": "2026-09-28T00:00:00.000Z", "period_start": "2026-09-21T00:00:00.000Z" },
"client_ip": "1.2.3.4",
"message": "API key verified successfully. You have PREMIUM tier access."
}POST/api/resolveProResolve a handle/username to associated profiles, breach data, and device exposures (Server-Sent Events stream)
Request parameters
handle- string (required) - The username/handle to resolve
Response
// text/event-stream — every frame is: data: {"type":"...","data":{...}}
// Frame types: init, x_profile, instagram_profile, instagram_details,
// instagram_availability, instagram_rich, tiktok_profile, tinder_profile,
// accounts, stealer_logs, discord_profiles, cross_ref_candidates,
// cross_ref_complete, complete, error.
// The platform frames are reserved: every one except tinder_profile currently
// carries null. Use POST /api/socialscrape/stream for live platform profiles.
// Aggregated payload once the stream finishes:
{
"success": true,
"data": {
"target": {
"handle": "johndoe",
"tinder": null,
"x": null,
"instagram": { "profile": null, "details": null }
},
"intelligence": { "former_usernames": [] },
"stealer_logs": {
"total_found": 3,
"results": [...],
"obfuscated": false
},
"accounts": { "total_found": 5, "results": [...] },
"discord_profiles": { "total_found": 1, "results": [...] },
"quota": { "remaining": 99, "limit": 100, "tier": "ENTERPRISE" }
}
}GET/api/socialscrape/platformsPublicSocialScrape module catalog — every id you can pass in platforms (public, no API key required)
Request parameters
mode- string (optional, query) - Filter the list: username, email, or phone
Response
{
"success": true,
"source": "live",
"catalog_release": "20260920T062338Z-923ce391de78",
"counts": { "username": 749, "email": 139, "phone": 22, "callable_single": 910 },
"categories": [{ "id": "tech_dev", "label": "Developer & Tech" }],
"platforms": [
{
"id": "github",
"label": "GitHub",
"mode": "username",
"category": "tech_dev",
"category_label": "Developer & Tech",
"callable": "single"
},
{
"id": "github_email",
"label": "GitHub (Email)",
"mode": "email",
"category": "tech_dev",
"category_label": "Developer & Tech",
"callable": "single"
},
{
"id": "instagram",
"label": "Instagram",
"mode": "username",
"category": "uncategorized",
"category_label": "Uncategorized",
"callable": "single"
}
]
}
// callable "single" -> usable alone or in a platforms[] subset for its mode.
// Use each entry's mode, not its suffix: spotify/yandex are email modules and
// vk_checkphone is a phone module. Retired ids are excluded from this list.
// counts always describe the whole catalog, even with ?mode=
// The catalog is read live from the upstream fleet and cached for one hour;
// module counts change as modules are added or retired. source is "live",
// "stale" (last-known-good) or "bundled" (cold-start snapshot); the numbers
// above are illustrative, not pinned.
// Cached 5 minutes; 30 requests/minute per IP.POST/api/socialscrape/scrapeProSocialScrape JSON lookup — one module, a subset, or the published username, email, or phone corpus
Request parameters
username- string (one of username/email/phone required) - Handle to look up
email- string - Email address; selects the email corpus
phone- string - Phone in E.164 format (+14155551234); selects the phone corpus
platforms- string[] (optional) - Ids from the matching mode catalog. One id = single-module lookup, several = subset, omitted = every published module in that corpus
Response
// Bodies:
// single module -> {"username": "torvalds", "platforms": ["github"]}
// all modules -> {"username": "torvalds"}
// email subset -> {"email": "[email protected]", "platforms": ["figma_email"]}
// phone subset -> {"phone": "+14155551234", "platforms": ["vk_checkphone"]}
{
"success": true,
"data": {
"username": "torvalds",
"results": {
"github": { "success": true, "profile": {...} },
"reddit": { "success": false, "error": "not found" }
},
"cross_references": { "discovered": [...], "total": 2 },
"scraped_at": "2026-09-10T03:14:01Z",
"status": "complete", "complete": true,
"expected": 2, "completed": 2, "failed": 0, "missing": 0
}
}
// 400 {"success": false, "error": "invalid_platforms", "invalid": ["githubb"], "message": "..."}
// Unknown, retired, or wrong-corpus ids are rejected before dispatch.
// Partial responses may have success:false and useful data.results. Retain them.
// status: complete | partial | timed_out | cancelled.
// expected = completed + missing; failed counts unresolved provider responses.
// complete:true means execution coverage, not proof of account ownership.
// Costs 0 social-search tokens on paid plans. Counts as one API request against your weekly budget; 1 request/second.GET/api/socialscrape/streamProServer-Sent Events version of the same lookup — each module result arrives as it lands
Request parameters
mode- string (optional, query) - username (default), email, or phone
username- string (query, username mode) - Handle to look up
x-ss-email- header (email mode) - The email address; sent as a header so the PII never lands in access logs
x-ss-phone- header (phone mode) - The E.164 phone number, header for the same reason
platforms- string (optional, query) - Comma-separated and/or repeated: platforms=github,reddit or platforms=github&platforms=reddit
Accept- header - text/event-stream
Response
# GET /api/socialscrape/stream?username=torvalds&platforms=github,reddit
# Authorization: Bearer sk_live_...
# Accept: text/event-stream
data: {"type":"result","platform":"github","result":{"success":true,"profile":{...}},"elapsed_ms":412}
data: {"type":"complete","username":"torvalds","total":2,"duration_ms":9120,"status":"complete","complete":true,"expected":2,"completed":2,"failed":0,"missing":0}
# Frame types: result | queued | overloaded | complete | error.
# Email mode: ?mode=email + header x-ss-email; optional platforms=figma_email
# Phone mode: ?mode=phone + header x-ss-phone; optional platforms=vk_checkphone
# platforms= selects upstream work; only the requested modules run.
# Omit it to run every published module in that corpus (wallet modules are separate).
# queued is a heartbeat; keep waiting. overloaded includes retryAfter seconds.
# A complete frame is terminal: inspect status/complete before declaring success.
# Partial or timed-out searches retain delivered results; missing checks are unknown.
# Provider errors are unresolved, not evidence that an account is absent.
# Allow queue + execution time (username 120s, email 60s, phone 30s) plus margin.
# Unknown, retired, or wrong-mode ids return a 400 invalid_platforms response.
# Counts as one API request against your weekly budget; 1 request/second.POST/api/database/searchProSearch breach records across connected sources for exposed credentials and personal data
Request parameters
type- string (required) - Search type: username, email, password, ip, name, phone
term- string (required) - The search term
offset- number (optional) - Pagination offset, default 0
limit- number (optional) - Results per page, default 25
Response
{
"success": true,
"data": {
"found": 15,
"elapsed": "0.234s",
"results": [
{
"id": "...",
"email": "[email protected]",
"password": "••••••••",
"source": { "name": "breach_2023", "date": "2023-06-15" }
}
],
"obfuscated": false
},
"quota": { "limit": 150, "remaining": 139, "period": "hour" }
}POST/api/stealer-logs/searchProSearch device exposures for compromised credentials — full results on Pro and above (50/day on Pro; each API call counts against your weekly API budget)
Request parameters
type- string (required) - Search type: email, username, domain, password
term- string (required) - The search term
limit- number (optional) - Results per page, default 35
offset- number (optional) - Pagination offset, default 0
sort- object (optional) - { field: "time_ingested", order: "desc"|"asc" }
Response
{
"success": true,
"data": {
"count": 12,
"elapsed": "0.156s",
"results": [
{
"id": "log_abc123",
"origin": "https://example.com/login",
"login": "[email protected]",
"password": "[REDACTED]",
"passwordCaptured": true,
"time_ingested": "2024-01-15T10:30:00Z"
}
],
"pagination": { "document_count": 12, "has_more": false },
"obfuscated": false
},
"quota": { "limit": 50, "remaining": 49, "period": "day" }
}POST/api/stealer-logs/file/[id]/[type]ProBrowse detailed contents of a stealer log file (Pro and above)
Request parameters
id- string (path) - The stealer log ID from search results
type- string (path) - File type: credentials, cookies, autofills, softwares, system, accounts
Response
{
"success": true,
"data": {
"count": 45,
"credentials": [
{ "origin": "https://bank.com", "login": "[email protected]", "password": "..." }
]
}
}POST/api/discord/lookupProLookup Discord user profiles by user ID
Request parameters
user_ids- string[] (required) - Array of Discord user IDs (max 10)
Response
{
"success": true,
"total_requested": 2,
"total_found": 2,
"profiles": [
{
"id": "123456789012345678",
"username": "user",
"discriminator": "0",
"avatar": "abc123...",
"banner": "def456...",
"accent_color": 16711680
}
]
}GET/api/saved-incidentsProList all saved credentials/incidents
Response
{
"success": true,
"incidents": [
{
"id": "...",
"sourceType": "stealer",
"origin": "https://example.com",
"login": "[email protected]",
"password": "[REDACTED]",
"createdAt": "2024-03-20T10:00:00Z"
}
]
}POST/api/saved-incidentsProSave a credential/incident to your account
Request parameters
sourceType- string (required) - "database" or "stealer"
origin- string (optional) - Origin URL
login- string (optional) - Login/username
password- string (optional) - Password
email- string (optional) - Email address
notes- string (optional) - Custom notes
Response
{
"success": true,
"incident": {
"id": "...",
"sourceType": "stealer",
"origin": "https://example.com",
"login": "[email protected]",
"createdAt": "2024-03-20T10:00:00Z"
}
}DELETE/api/saved-incidents/[id]ProDelete a saved incident by ID
Request parameters
id- string (path) - The incident ID to delete
Response
{
"success": true,
"message": "Incident deleted"
}GET/api/auth/meProGet current account information, tier, quota, and verify API key
Response
{
"success": true,
"email": "[email protected]",
"userId": "...",
"tier": "ENTERPRISE",
"auth_method": "api_key",
"client_ip": "1.2.3.4",
"quota": {
"used": 10,
"limit": 100,
"remaining": 90,
"period": "hour"
},
"stealerQuota": {
"used": 0,
"limit": 0,
"remaining": 0,
"period": "day"
}
}Rate limits & quotas
API requests are metered per week on search endpoints (resolve, SocialScrape scrape and stream, breach search, device-exposure search, Discord lookup, people search, AI analysis) and reset every Monday at 00:00 UTC. They are separate from the dashboard quotas, which are shown for reference.
| Plan | API | API requests | Rate | IPs | Dashboard: Breach Lookups | Dashboard: Social Lookups | Dashboard: Device Exposures |
|---|---|---|---|---|---|---|---|
| Free | — | — | — | — | 10/day (preview) | 10/day (preview) | — |
| Starter ($12.99/mo) | — | — | — | — | 50/day | 25/day | — |
| Basic | — | — | — | — | Unlimited | 150/day | — |
| Pro | ✓ | 500/week | 1 req/s | 3 | Unlimited | 500/day | 50/day |
| Elite (no longer sold) | ✓ | 500/week | 3 req/s | 5 | Unlimited | Unlimited | 100/day |
| Enterprise | ✓ | Custom | Custom | Custom | Custom | Custom | Custom |
API access: Available from the Pro plan and up. Pro includes 500 API requests per week at 1 request/second and 3 whitelisted IPs. For higher API volume, contact sales about Enterprise. Once enabled, configure allowed IPs in Dashboard → Settings → API Access before using the API.
Error responses
| Code | Status | Description |
|---|---|---|
400 | Bad Request | Invalid request body or missing required parameters |
401 | Unauthorized | Missing or invalid API key |
403 | Forbidden | IP not whitelisted or insufficient tier access |
404 | Not Found | Resource not found |
409 | Conflict | Resource already exists (e.g., duplicate saved incident) |
429 | Too Many Requests | Rate limit or quota exceeded |
429 | API_WEEKLY_LIMIT | Weekly API budget used; resets Monday 00:00 UTC (see Retry-After) |
429 | API_RATE_LIMITED | More than 1 request/second |
500 | Internal Server Error | Server error - contact support if persistent |
Error response format
{
"success": false,
"error": "Error message",
"message": "Human-readable description"
}Response headers
Rate limit information is included in response headers:
X-RateLimit-Limit- Maximum requests per second
X-RateLimit-Remaining- Remaining requests in window
X-RateLimit-Reset- Unix timestamp when limit resets
X-API-Weekly-Limit- API requests included per week on your plan
X-API-Weekly-Remaining- API requests left in the current week
X-API-Weekly-Reset- ISO timestamp when the weekly budget resets (Monday 00:00 UTC)
X-API-Authenticated- "true" when authenticated
X-Client-IP- Your detected IP address
Troubleshooting
403 Forbidden or Cloudflare Challenge
If you receive 403 errors or see Cloudflare challenge pages:
- Check your IP via
GET /api/v1/info - Whitelist IP in Dashboard → Settings → API Access
- Verify key via
GET /api/v1/verify - Confirm your account has API access (Pro and above, or an Enterprise plan)
IP Mismatch
Your server's outgoing IP may differ from local, especially with:
- Cloud providers (AWS, GCP, Azure): use the instance public IP
- VPNs and proxies: whitelist the exit node IP
- NAT gateways: whitelist the NAT public IP
Required headers
Authorization: Bearer sk_live_your_api_key
Content-Type: application/jsonReady to integrate?
API access is included on Pro and above with 500 API requests per week. For higher API volume, team seats, or an SLA, get in touch about an Enterprise plan.