Revealer / API reference

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.

Base URLhttps://revealer.usStart building

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
01

Quick start

  1. 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. 2

    Make Request

    Send authenticated REST requests

  3. 3

    Get Results

    Receive structured JSON responses

02

Authentication

Include your API key in the Authorization header:

Authorization: Bearer sk_live_your_api_key

Security: Never expose your API key in client-side code. Make API calls from your backend.

03

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")

04

Endpoints

14 endpoints
GET/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"
  }
}
05

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.

PlanAPIAPI requestsRateIPsDashboard: Breach LookupsDashboard: Social LookupsDashboard: Device Exposures
Free10/day (preview)10/day (preview)
Starter ($12.99/mo)50/day25/day
BasicUnlimited150/day
Pro500/week1 req/s3Unlimited500/day50/day
Elite (no longer sold)500/week3 req/s5UnlimitedUnlimited100/day
EnterpriseCustomCustomCustomCustomCustomCustom

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.

06

Error responses

CodeStatusDescription
400Bad RequestInvalid request body or missing required parameters
401UnauthorizedMissing or invalid API key
403ForbiddenIP not whitelisted or insufficient tier access
404Not FoundResource not found
409ConflictResource already exists (e.g., duplicate saved incident)
429Too Many RequestsRate limit or quota exceeded
429API_WEEKLY_LIMITWeekly API budget used; resets Monday 00:00 UTC (see Retry-After)
429API_RATE_LIMITEDMore than 1 request/second
500Internal Server ErrorServer error - contact support if persistent

Error response format

{
  "success": false,
  "error": "Error message",
  "message": "Human-readable description"
}
07

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
08

Troubleshooting

403 Forbidden or Cloudflare Challenge

If you receive 403 errors or see Cloudflare challenge pages:

  1. Check your IP via GET /api/v1/info
  2. Whitelist IP in Dashboard → Settings → API Access
  3. Verify key via GET /api/v1/verify
  4. 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/json
Get started

Ready 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.