Skip to main content

fingerprintchecker (Python)

Install with pip install fingerprintchecker; import it as fpchecker.

Server SDK for FingerPrintChecker. Python 3.9+, standard-library HTTP, one runtime dependency (cryptography, for sealed results).

from fpchecker import FpChecker, unseal_result, verify_webhook_signature, FpCheckerApiError

fp = FpChecker(os.environ["FPCHECKER_SECRET_KEY"])
verdict = fp.check_eligibility({"visitorId": "v_..."})
if verdict.get("ok") is False:
    print("refused:", verdict.get("error") or verdict.get("reason"))

Client

FpChecker(secret_key, base_url="https://api.fpchecker.com", timeout=10, *, publishable_key=None) has one method per OpenAPI operationId, in snake_case: create_intent, get_challenge, identify, bot_check, check_eligibility, release_eligibility, check_quota, bind_subject, relate_subjects, send_feedback, get_claim_flags, search_events, get_event, update_event, get_visitor, delete_visitor, get_health, get_status. Bodies and query parameters are plain dicts; responses are dicts.

  • The secret key goes in the X-Secret-Key header, never in a URL, and is not shown by repr(). get_challenge and identify use the publishable key (publishable_key=) in X-Publishable-Key instead; get_health and get_status send no key.
  • 2xx responses are returned as data, including refusals such as {"ok": False, "error": ...}. Check ok.
  • Non-2xx raises FpCheckerApiError with status, code (error or reason from the body), retry_after (seconds) and body.
  • Network failures and timeouts also raise FpCheckerApiError, with status 0, code "network_error" or "timeout", and the original exception as __cause__.
  • Redirects are never followed (they would forward the secret key to another origin). base_url must be https, except localhost, 127.0.0.1 and [::1] (otherwise ValueError).
  • timeout (positive finite seconds) applies per network operation (connect, each read), not to the whole call.
  • Only GET requests retry (429, 5xx, network failures and timeouts; at most 2 retries, honouring Retry-After, wait capped at 10 s). POST, PATCH and DELETE are never retried.

Bot check

bot_check(*, method, url, ip, headers) classifies a request your backend received (header-only: no script ran in the sender). It is not charged and writes no event. Forward the original URL (the host and scheme the visitor used, not your origin behind a CDN or load balancer) and the client IP. bot_check_headers keeps only the headers the check needs and drops Cookie, Authorization and everything else.

import os

from fastapi import FastAPI, Request
from fastapi.concurrency import run_in_threadpool
from fastapi.responses import JSONResponse
from fpchecker import FpChecker, FpCheckerApiError, bot_check_headers

fp = FpChecker(os.environ["FPCHECKER_SECRET_KEY"])
app = FastAPI()

@app.middleware("http")
async def block_bad_bots(request: Request, call_next):
    if request.client is None:  # no peer address (e.g. some test clients): nothing to check
        return await call_next(request)
    try:
        verdict = await run_in_threadpool(  # bot_check blocks; keep it off the event loop
            fp.bot_check,
            method=request.method,
            url=str(request.url),  # original host and scheme; behind a proxy rebuild it from X-Forwarded-*
            ip=request.client.host,  # behind a proxy use the forwarded client address
            headers=bot_check_headers(request.headers),
        )
    except FpCheckerApiError:
        return await call_next(request)  # fail open: an outage of the check must not take your site down
    if verdict["bot"]["result"] == "bad":
        return JSONResponse({"error": "forbidden"}, status_code=403)
    return await call_next(request)  # "good" = a verified or signed directory bot; verdict["bot"]["info"] says which

bot.result is good, bad or not_detected; bot.info (id, name, provider, category, identity) is set when the request named a directory bot. A 400 raises FpCheckerApiError with code invalid_request or invalid_ip and the offending field in body.

Rules of use:

  • Call bot_check once per request and reuse the answer; do not call it again for the same request.
  • Never retry a signed request: a retry replays the signature nonce and the request is then judged spoofed (bad).
  • ip must be the trusted client IP, not an address a client can set. With FastAPI run uvicorn with --proxy-headers and --forwarded-allow-ips set to your proxy's address (not *), then use request.client.host.
  • Limits: 3,000 checks per minute per client IP and 1,200 per minute per project (429 beyond that).
  • bot_check_headers also forwards any header named in the request's signature-input, so signed agents verify; Cookie and Authorization are never forwarded.

parse_webhook_event returns signals_version (1 before server 0.48.0, 2 since) and bot (BotSignals: result may be good, types, info as BotInfo or None). search_events also filters by bot_result, bot_category, bot_identity and bot_id.

Sealed results

result = unseal_result(identify_response["sealedResult"], [os.environ["FPC_SEALED_KEY"]])

Pass every active key (active and previous during rotation). Raises SealedResultError with .code of bad_format, unknown_key, decrypt_failed, invalid_key or unsupported_version.

Webhooks

# raw_body must be the exact bytes received, not a re-serialised object.
verify_webhook_signature(request.body, request.headers["FPC-Signature"], os.environ["FPC_WEBHOOK_SECRET"])

Raises WebhookSignatureError with .code of malformed_header, bad_signature, expired or future. tolerance_sec (default 300) must be a finite number >= 0, else TypeError / ValueError.

License

Apache-2.0

Metadata

Release files for fingerprintchecker 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fingerprintchecker 0.4.0
File Size Uploaded Provenance
fingerprintchecker-0.4.0.tar.gz 24.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for fingerprintchecker 0.4.0
File Interpreter ABI Platform
fingerprintchecker-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 43.9 kB

Release files / fingerprintchecker-0.4.0.tar.gz

Download URL fingerprintchecker-0.4.0.tar.gz
Size 24.9 kB
Tags Source
SHA-256 checksum
How to use checksums
a6f292d24fd14c84949324940fe49e68ebe6347ceaafb18d6b942697c84b9d38
BLAKE2b-256 checksum
How to use checksums
7aedc7711700ce632a995558f76a1071b7696acb4faa709f19503a0e49785561
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Release files / fingerprintchecker-0.4.0-py3-none-any.whl

Download URL fingerprintchecker-0.4.0-py3-none-any.whl
Size 18.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
108384f1f19ae67404288fe9c9af2cf281cc33ef3fb59fe5b0f9069f2ef2d0ce
BLAKE2b-256 checksum
How to use checksums
c2a61118366b2ee7779c9a310e9acb49dcad99264350f7aeb77dd8f69b705aa2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Security for fingerprintchecker 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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