API
Run the same searches as the site from your own code: emails, phone numbers, usernames and names across every source, and the lookup tools. Each request is a JSON POST, and results stream back as they arrive, one JSON object per line.
Get an API key
Make one on the API keys page. A search costs 1 credit, the same as on the site. $500 buys 1,600 credits and $1,000 buys 3,500, $0.29 a credit at the top.
Authentication
Send your key in the x-api-key header and the body as JSON, with content-type: application/json. A key is 48 characters, 0 to 9 and a to f. The short code next to a key on the API keys page only tells keys apart and won’t work in its place.
Search
Each search costs 1 credit. A username search uses one of your free username searches first, if you have any left today. If most sources fail and nothing is found, the credit is given back.
Body
email phone username nameLines in the response
import json, requests
resp = requests.post(
"https://api.osint.sx/search",
headers={"x-api-key": "YOUR_API_KEY", "content-type": "application/json"},
json={"moduleType": "email", "identifier": "river.hale@example.com"},
stream=True,
)
if resp.status_code != 200:
raise SystemExit(f"{resp.status_code}: {resp.json()['error']}")
for line in resp.iter_lines(decode_unicode=True):
if not line:
continue
data = json.loads(line)
if "result" in data and "show" in data["result"]:
print(data["className"], data["result"]["show"])Tools
Same header, same newline-delimited JSON. A $50 credit pack or bigger adds free tool searches every day for 30 days; after those, and without one, each search costs 1 credit. A search that finds nothing, or fails, costs nothing.
Endpoints, all POST
Body
name email domain gaiaId. Microsoft: name email domain cid. Epic: username accountId platform. X: username user_id url.xbl psn steam nintendo discord twitch github google apple facebook.Lines in the response
import json, requests
resp = requests.post(
"https://api.osint.sx/google/search",
headers={"x-api-key": "YOUR_API_KEY", "content-type": "application/json"},
json={"queryType": "email", "query": "river.hale@example.com"},
stream=True,
)
if resp.status_code != 200:
raise SystemExit(f"{resp.status_code}: {resp.json()['error']}")
for line in resp.iter_lines(decode_unicode=True):
if not line:
continue
msg = json.loads(line)
if msg["type"] == "result":
print(msg["data"])Rate limits
Up to 10 searches can run at once per account. Each key, and each IP address, also has a limit per minute; responses carry RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset headers for it. Over a limit you get a 429. A 503 when the service is busy comes with a Retry-After header in seconds.
Errors
A refused request gets a status code and a JSON body with the reason, like {"error": "No searches remaining"}.