Python SDK
Official osintverse package for the SearchIn API — install, auth, create, wait, bulk, unlock, premium, and errors.
Official client for the SearchIn API on osintverse.com. Same providers, prices, and prepaid wallet as the SearchIn UI.
pip install osintverseRequires Python 3.10+. Package: osintverse on PyPI. Source: osintverse-pythonsdk.
It talks to https://apiv1.osintverse.com. It is not affiliated with other products that reuse the OSINTverse name.
SearchIn API only
This SDK covers SearchIn lookups (create, poll, bulk, LeakRadar unlock, OSINT Industries premium). GraphIn — seed, canvas, path, share — stays in the GraphIn UI. Create keys in Dashboard → API keys; there is no key-management API.
Authenticate
Create a key (prefix ov_). Copy it once.
export OSINTVERSE_API_KEY=ov_your_api_keyfrom osintverse import OSINTverse
client = OSINTverse() # or OSINTverse(api_key="ov_your_api_key")Close the HTTP client when you are done, or use a context manager:
with OSINTverse() as client:
search = client.search.create(
provider="leakradar-lite",
input_type="email",
query="[email protected]",
wait=True,
)client.health() and client.providers.list() work without a key. Search methods require one. Optional: OSINTverse(base_url="https://apiv1.osintverse.com", timeout=60).
First search
search = client.search.create(
provider="leakradar-lite",
input_type="email",
query="[email protected]",
wait=True,
)
print(search.id, search.status, search.cost_usd, search.balance_after)
if search.result:
for match in search.result.matches:
print(match)Pick a valid provider + input_type from client.providers.list() or the pricing matrix. Invalid pairs raise ValidationError (HTTP 422).
Most providers finish in the create response. FaceCheck image jobs often return running — wait=True polls every ~2 seconds (default timeout 120s).
Methods
| SDK | HTTP |
|---|---|
client.health() | GET /health |
client.providers.list() | GET /v1/providers |
client.search.create(...) | POST /v1/search |
client.search.bulk(...) | POST /v1/search/bulk |
client.search.retrieve(id) / .get(id) | GET /v1/search/{id} |
client.search.wait(id) | poll retrieve until terminal |
client.search.unlock(id) | POST /v1/search/{id}/unlock |
client.search.premium(id) | POST /v1/search/{id}/premium |
create / bulk kwargs: premium=False, wait=False, poll_interval=2, timeout=120.
Without wait, inspect search.status and poll yourself:
search = client.search.create(
provider="facecheck",
input_type="image",
query="https://example.com/photo.jpg",
)
if search.running:
search = client.search.wait(search.id)Each poll counts toward the 1,000 requests/day/key limit. See authentication.
Results
A Search object mirrors the API job: id, status, provider, input_type, query, cost_usd, balance_after, error, poll_url, result.
result.matches— normalized rows to consume in a pipeline (shape varies by provider).result.sources— adapter metadata (counts, paging).- Provider field notes: provider guides.
- Status meanings: search workflow.
Bulk
batch = client.search.bulk(
input_type="email",
queries=["[email protected]", "[email protected]"],
providers=["leakradar-lite", "dehashed"],
wait=True,
)
print(batch.batch_id, batch.estimated_cost_usd, batch.summary)
for job in batch.searches:
print(job.provider, job.query, job.status)Limits: 50 queries, 100 jobs (queries × providers). Partial success is normal. Bulk wait=True polls every running job and does not raise if a sibling is failed or refunded — read batch.summary. Each job counts toward the daily key quota (one HTTP create, N billable searches).
LeakRadar unlocks and OSINT Industries premium
client.search.unlock(search.id) # leftover LeakRadar credentials; $0.50 / 1k
client.search.premium(search.id) # premium modules after a basic OSINT Industries search; +$1.80Or at create: client.search.create(..., premium=True) (OSINT Industries only; ignored on other providers). Insufficient extra balance raises PaymentRequiredError (HTTP 402). Already-unlocked / already-premium jobs return the current search with no extra charge.
Async
from osintverse import AsyncOSINTverse
async with AsyncOSINTverse() as client:
search = await client.search.create(
provider="leakradar-lite",
input_type="email",
query="[email protected]",
wait=True,
)Same method names, all awaited.
Errors
HTTP { "detail": "…" } maps to:
| Status | Exception |
|---|---|
| 401 | AuthenticationError |
| 402 | PaymentRequiredError |
| 403 | ForbiddenError |
| 404 | NotFoundError |
| 422 | ValidationError |
| 5xx | APIError |
A 200 job can still fail. wait=True on create raises:
SearchFailedError— usually insufficient balance (status: failed, not charged)SearchRefundedError— upstream failed after billing (status: refunded)WaitTimeoutError— stillrunningaftertimeout
from osintverse import SearchFailedError, ValidationError
try:
search = client.search.create(
provider="leakradar-lite",
input_type="email",
query="[email protected]",
wait=True,
)
except ValidationError as exc:
print("Bad provider/input_type:", exc)
except SearchFailedError as exc:
print(exc.search.error)Top up at Billing before you automate. Full HTTP table: errors.