Skip to main content

sentinelsup — Sentinel Python SDK

Official Python SDK for Sentinel — a real-time fraud detection API that flags VPNs, residential proxies, antidetect browsers (Kameleo, GoLogin, Multilogin), Tor exit nodes, and AI bots in under 40 ms.

PyPI Python versions license

Zero dependencies — just the standard library. Works with Flask, Django, FastAPI, or bare urllib.

Set up with AI (fastest)

Using Claude Code, Cursor, Copilot, or any AI coding assistant? Paste this one prompt and it wires the whole integration — frontend script, backend check, env var, and a test:

Fetch https://sntlhq.com/integrate.md and follow it to add Sentinel fraud protection to this app — protect signup, login, and checkout. My API key is sk_live_YOUR_KEY; put it in a SENTINEL_KEY env var, never in client-side code. Then show me how to test it.

integrate.md is the canonical machine-readable integration guide, kept in sync with the live API.

Install

pip install sentinelsup

Python 3.8+. Get a free API key (no credit card) at sntlhq.com/signup.

Quick start

import os
from sentinel import Sentinel

s = Sentinel(api_key=os.environ["SENTINEL_KEY"])  # or omit — reads the env var itself

result = s.evaluate(token=request.json["sentinelToken"])  # token from the frontend SDK

if result.is_blocked:            # decision == 'block'
    abort(403)

print(result.decision)        # 'allow' | 'review' | 'block' — route on this
print(result.risk_score)      # 0..100
print(result.network)         # {'vpn': True, 'proxy': False, 'datacenter': True, ...}
print(result.reasons)         # ['vpn_detected', 'datacenter_asn', ...]

Check the signup email against the disposable-domain feed (checked transiently, never stored), or look up an arbitrary IP with no browser token at all:

result = s.evaluate(token=tok, email=data["email"])
if result.raw.get("email", {}).get("disposable"):
    ...  # burner domain — decision is escalated allow → review

info = s.lookup("185.220.101.34")   # GET /v1/lookup/{ip} — same key & quota
print(info["verdict"])              # 'allow' | 'review' | 'block'
print(info["signals"])              # {'vpn': ..., 'proxied': ..., 'tor': ..., 'dch': ..., 'anon': ...}

email= and lookup() ship in the next PyPI release (0.2.1) — on PyPI today, use the raw HTTP endpoints documented at sntlhq.com/api until it lands.

What you get back

evaluate() returns an EvaluateResult dataclass:

@dataclass
class EvaluateResult:
    decision: str | None        # 'allow' | 'review' | 'block'
    risk_score: int | None      # 0..100
    ip: str | None
    country: str | None         # ISO-2
    network: dict               # {vpn, proxy, datacenter, anonymous, tor, residential, service}
    device: dict                # antidetect / automation / emulator signals
    reasons: list[str]          # machine-readable codes
    raw: dict                   # full upstream response

    is_suspicious: bool         # True if decision != 'allow'
    is_blocked: bool            # True if decision == 'block'

Try the live sample (same shape, no key needed):

curl "https://sntlhq.com/v1/evaluate/sample?scenario=vpn"

Or use the interactive playground.

Frontend setup

Add the Sentinel SDK to your frontend. One script loads both layers — network (VPN/proxy/datacenter) and device (antidetect/bot/tampering):

<script async src="https://sntlhq.com/assets/sentinel.js"></script>

<!-- Add class="monocle-enriched" to any form you want evaluated -->
<form class="monocle-enriched" id="signup-form">
  <!-- The SDK injects both:
       <input type="hidden" name="monocle"     value="eyJ...">  (network)
       <input type="hidden" name="sentinel_fp" value="a1b2..."> (device) -->
</form>

Forward both fields to your backend with the form submission and pass them to evaluate() as token and fingerprint_event_id — without the second one, the device-layer signals (antidetect, automation, emulator) never fire. For fetch/XHR submissions, collect them explicitly:

const { token, fingerprintEventId } = await window.Sentinel.collect();

Examples

Flask — block VPN/proxy signups

from flask import Flask, request, abort, jsonify
from sentinel import Sentinel, SentinelError

app = Flask(__name__)
sentinel = Sentinel()  # reads SENTINEL_KEY (or SENTINEL_API_KEY) from env

@app.route("/signup", methods=["POST"])
def signup():
    data = request.get_json()
    try:
        result = sentinel.evaluate(token=data["sentinelToken"])
    except SentinelError as e:
        # Fail open OR fail closed — your call. Logged either way.
        app.logger.warning("Sentinel error: %s", e)
        result = None

    if result and result.is_blocked:
        abort(403, "Signup blocked")

    # ... your normal signup flow
    return jsonify({"ok": True})

Django — middleware for high-value endpoints

from django.http import JsonResponse
from sentinel import Sentinel

sentinel = Sentinel()  # reads SENTINEL_KEY (or SENTINEL_API_KEY) from env

class FraudCheckMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if request.path.startswith("/api/checkout"):
            token = request.META.get("HTTP_X_SENTINEL_TOKEN")
            if token:
                try:
                    result = sentinel.evaluate(token=token)
                    if result.is_blocked:
                        return JsonResponse({"error": "blocked"}, status=403)
                except Exception:
                    pass  # fail open
        return self.get_response(request)

Runnable versions live in examples/.

API

Sentinel(api_key=None, endpoint="https://sntlhq.com", timeout=5.0)

Option Default Description
api_key $SENTINEL_KEY (falls back to $SENTINEL_API_KEY) Your key starting with sk_live_
endpoint https://sntlhq.com Override base URL (for testing)
timeout 5.0 Per-request timeout in seconds

sentinel.evaluate(token, fingerprint_event_id=None, account_id=None, email=None)

Returns EvaluateResult. Raises SentinelError on network/API failure.

  • fingerprint_event_id — adds the device signal block (antidetect, automation, emulator, …).
  • account_id — your own user id for this session; enables multi-accounting detection (device.linked_accounts / device.multi_account).
  • email — adds email.disposable to the raw response; burner domains escalate allow to review.

sentinel.lookup(ip)

Returns the raw response dict for any public IPv4/IPv6 address (wraps GET /v1/lookup/{ip}): verdict (allow/review/block), risk_score (0–100), known, signals ({vpn, proxied, tor, dch, anon} or None), network ({asn, org, country, city}), latency_ms. Shares the per-key hourly quota with evaluate(). known: False means our feeds hold no data — it is not a clean guarantee.

Errors

All failures raise SentinelError. The exception carries .status (HTTP code) and .body (parsed error body) when available.

from sentinel import Sentinel, SentinelError

try:
    result = sentinel.evaluate(token=tok)
except SentinelError as e:
    if e.status == 429:
        pass    # back off
    elif e.status and 400 <= e.status < 500:
        pass    # bad input, won't recover by retrying
    else:
        pass    # transient — retry once or fail open

Rate limits

Free tier: 1,000 requests/hour per API key. No monthly cap, no credit card. Upgrade at sntlhq.com when you need more.

What Sentinel detects

VPNs (commercial + self-hosted) · residential proxies (Bright Data, IPRoyal, and similar networks) · datacenter IPs · Tor exit nodes · antidetect browsers (Kameleo, GoLogin, Multilogin, Dolphin{anty}, AdsPower) · headless browsers and automation (Puppeteer, Playwright, Selenium) · AI agents · emulators and virtual machines · browser tampering.

Related

License

MIT © Sentinel Edge Networks LTD. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sentinelsup-0.2.1.tar.gz (9.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sentinelsup-0.2.1-py3-none-any.whl (8.5 kB view details)

Uploaded Python 3

File details

Details for the file sentinelsup-0.2.1.tar.gz.

File metadata

  • Download URL: sentinelsup-0.2.1.tar.gz
  • Upload date:
  • Size: 9.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.14

File hashes

Hashes for sentinelsup-0.2.1.tar.gz
Algorithm Hash digest
SHA256 2a1fb5c9bb35fec0fb1773feb210236c346c430c7bf27ebaae8ad912362982e2
MD5 5333ce5d975aee7f3b3ab417efdd4213
BLAKE2b-256 8ba8301f3aa76dca42ce3cba96ab595fcfab8cfb071eddd8eba2bdf37a718075

See more details on using hashes here.

File details

Details for the file sentinelsup-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: sentinelsup-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 8.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.14

File hashes

Hashes for sentinelsup-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 39231e4ca36778654a15f93815ac714db8b951670bd9eb4e07da8bd2c89fc9a9
MD5 22e466518ff90d1199a1bedc2b4e94e4
BLAKE2b-256 880a63035f26f0263a59f243de701d1e45ac92381827d9fb51d689dfb12430e2

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.3

2 files

0.2.2

2 files

This release

0.2.1 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page