API Overview Beta

The Privshot API lets you detect and redact personally identifiable information (PII) from images programmatically. Send an image, get back bounding boxes or a clean redacted PNG — your choice.

All requests go to https://privshot.com/api/v1. The API accepts multipart/form-data uploads and responds with JSON or binary PNG depending on the endpoint.

No account required to try the web editor. An API key is only needed for programmatic access.
Detection is best-effort — review before you trust it. Unlike the web editor, an API call has no human in the loop, so a missed region ships straight into your pipeline. Every response now carries a per-box score and a review_recommended flag (see Detection quality & review) — gate on them for anything sensitive. Where the API is strongest today: structured identifiers (IBAN, credit cards, SSN and other national IDs) are matched by checksum-validated patterns and are highly reliable; free-text names and addresses depend on OCR + NLP and are more likely to be missed.

Interactive preview

See how each option changes the output on a sample screenshot — the preview runs entirely in your browser on pre-detected regions, so it costs no credits and needs no API key.

#000000

✓ Paid-plan options are active in this preview.

Preview only · runs in your browser · no credits used.

Equivalent request

Authentication

Pass your API key in the X-Api-Key header with every request.

X-Api-Key: ps_your_api_key_here

You can create and manage API keys from your dashboard. Keys start with ps_.

Keep your API key secret. Never expose it in client-side code or public repositories.

Errors

All errors return a JSON body with an error field describing the problem.

HTTP statusMeaning
400Bad request — missing/invalid file, or an invalid option value
401Missing or invalid API key
402Insufficient credits (paid tier only)
403Email not verified, or a paid-only option used on a free request
409A request with the same Idempotency-Key is already in progress
429Rate limit or daily quota exceeded
500Internal server error — please retry
"error": "Daily limit reached. Upgrade to a paid key or try again tomorrow."

GET /health

GET /api/v1/health

Check that the API is reachable. No authentication required.

Response

{ "status": "ok", "version": "1", "beta": true, "free_daily_limit": 20, "languages": ["en", "fr", "de", "es", "it"] }

GET /entities

GET /api/v1/entities

List the entity types, languages and region scopes the engine supports. Use the entities values for the entities/allow options, the languages for language, and the regions for region. No authentication required.

Response

{ "entities": ["PERSON", "EMAIL_ADDRESS", "IBAN_CODE", "CA_SIN", "FR_NIR", "DE_PASSPORT", /* …52 total */ ], "languages": ["en", "fr", "de", "es", "it"], "regions": ["eu", "na", "fr", "us", /* … country codes */ ] }

POST /analyze

POST /api/v1/analyze

Detect PII in an image and return bounding boxes with entity labels. The original image is not modified — this is a read-only detection call.

Useful for previewing what will be redacted before committing, or for building your own rendering pipeline.

Request

FieldTypeDescription
file requiredFileImage to analyze. PNG, JPEG, or WEBP. Max 20 MB.
entities optionalStringComma-separated entity types to detect. Defaults to all. See Redaction options.
allow optionalStringComma-separated entity types to exclude from the result.
min_confidence optionalNumberMinimum detection confidence, 01 (default 0.4).
language optionalStringOCR + name/location language (default en). See options.
region optionalStringCountry/region scope for national IDs (e.g. fr, eu). See Region scopes.

Send an Idempotency-Key header to make retries safe (see Idempotency).

Example

curl -X POST https://privshot.com/api/v1/analyze \ -H "X-Api-Key: ps_your_key_here" \ -F "file=@screenshot.png" \ -F "entities=EMAIL_ADDRESS,CREDIT_CARD" \ -F "language=fr" \ -F "region=fr"

Response

{ "entities_found": ["EMAIL_ADDRESS", "PERSON"], "image_width": 1024, "image_height": 512, "regions_count": 2, "min_confidence_found": 0.6, "review_recommended": true, "boxes": [ { "x": 142, "y": 58, "w": 210, "h": 24, "label": "PERSON", "score": 0.6 }, { "x": 142, "y": 90, "w": 310, "h": 24, "label": "EMAIL_ADDRESS", "score": 1.0 } ] }

Coordinates (x, y, w, h) are in pixels relative to the original image dimensions. Each box carries a score (0–1 detection confidence); the top-level regions_count, min_confidence_found and review_recommended summarise the result — see Detection quality & review.

POST /redact

POST /api/v1/redact

Detect PII and return a redacted image with all sensitive regions obscured. Supports JSON (base64) or raw binary PNG output, plus the redaction options below.

Request

FieldTypeDescription
file requiredFileImage to redact. PNG, JPEG, or WEBP. Max 20 MB.
format optionalStringjson (default) or binary for a raw PNG stream.
entities, allow, min_confidence freeString / NumberSame as /analyze. Control what gets detected and redacted.
language, region freeStringSame as /analyze. Language and country/region scope.
color freeStringHex fill colour for boxes, e.g. #ff0000 (default black).
style paidStringbox (default), blur, or pixelate.
padding paidIntegerExpand each redacted region by N pixels (0–100).
show_labels paidBooleanStamp the entity type above each region.
Paid-only options (style blur/pixelate, padding, show_labels) return 403 on a free request. Basic options work on every tier.

Examples

Binary PNG, blur style, keep names visible

curl -X POST "https://privshot.com/api/v1/redact?format=binary" \ -H "X-Api-Key: ps_your_key_here" \ -F "file=@screenshot.png" \ -F "style=blur" \ -F "allow=PERSON" \ --output redacted.png

JSON response

{ "redacted": "iVBORw0KGgoAAAANS...", // base64 PNG "entities_found": ["EMAIL_ADDRESS", "CREDIT_CARD"], "image_width": 1024, "image_height": 512, "watermarked": false, "regions_count": 2, "min_confidence_found": 0.5, "review_recommended": true }

binary responses carry the same signal as headers: X-Regions-Count and X-Review-Recommended. For per-region scores, call /analyze.

Free-tier API keys include a privshot.com watermark on redacted output. Upgrade to a paid key to remove it.

Redaction options

Options are sent as extra multipart/form-data fields (or query parameters) alongside the file. They apply to both /analyze and /redact where relevant.

OptionTierValuesEffect
entitiesFreecomma listDetect only these types (default: all).
allowFreecomma listDetect everything but leave these types visible.
min_confidenceFree0–1Detection threshold (default 0.4). Lower = higher recall (catches more, over-redacts more); higher = fewer false positives (but more misses). For sensitive data, prefer a lower value — an extra black box is safer than a leaked identifier — and review with the confidence scores.
languageFreeen · fr · de · es · itOCR + name/location language (default en).
regionFreecountry code · eu · naRestricts detection to that country/region's national IDs + universal types — other countries' IDs are not searched, so look-alike patterns can't false-positive. Default: all countries. An explicit entities list overrides it. See scopes below.
colorFree#RRGGBBFill colour of solid boxes.
stylePaidbox · blur · pixelateObfuscation style. box and pixelate are irreversible; blur is sized to fully destroy the text.
paddingPaid0–100Expand each region by N pixels for safer coverage.
show_labelsPaidtrue / falseDraw the detected entity type above each region.
Valid entity type values come from GET /entities. Unknown values return 400.

Region scopes

region accepts a country code, or a region that expands to several countries. Only that scope's national IDs plus the universal types are detected.

ValueScope
naus, ca
eugb, fr, es, it, de, pl, fi, se, ch, nl, be, ie
country us United States · ca Canada · gb United Kingdom · fr France · es Spain · it Italy · de Germany · pl Poland · fi Finland · se Sweden · ch Switzerland · nl Netherlands · be Belgium · ie Ireland

Detection quality & review

Privshot detects PII with OCR plus pattern and NLP matching. It is best-effort: it will not catch 100% of PII 100% of the time, and it has no human review step when called through the API. Treat every redaction as a draft your system must validate before trusting it — a missed region is an un-redacted leak.

What every response gives you

FieldWhereMeaning
scoreeach box (/analyze)Detection confidence, 0–1. Lower means less certain.
regions_countJSON body · X-Regions-Count headerHow many regions were detected/redacted.
min_confidence_foundJSON bodyLowest confidence among the returned regions (null if none).
review_recommendedJSON body · X-Review-Recommended headertrue when a region is below 0.6 confidence, or when nothing was detected — either may warrant a manual look.

Recommended workflow for sensitive data

  1. Call /analyze first and inspect each box score.
  2. Gate on review_recommended — route those images to a human or re-run with a lower min_confidence.
  3. Bias toward over-redaction: a lower threshold blacks out more, which is safer than missing an identifier.
  4. Rely on structured identifiers (IBAN, cards, SSN, national IDs) where you can — they are checksum-validated and far more reliable than free-text name/address detection.
Privshot does not guarantee complete PII removal and is not a substitute for your own compliance review. You remain responsible for validating output before disclosure. Images are processed in memory and never used to train models.

Idempotency

Send an Idempotency-Key header (any unique string, e.g. a UUID) to make retries safe. If the same key is replayed within 24 hours, the API returns the original response — without processing or charging again — and sets Idempotent-Replayed: true.

curl -X POST https://privshot.com/api/v1/redact \ -H "X-Api-Key: ps_your_key_here" \ -H "Idempotency-Key: 3f9c-...-a1" \ -F "file=@screenshot.png"

A concurrent request reusing a key that is still processing returns 409. Reuse a key only for identical retries of the same request.

Usage headers

Every authenticated response includes your remaining allowance and rate-limit state:

HeaderMeaning
X-Credits-RemainingCredits left (paid requests).
X-Free-Requests-RemainingFree requests left today (free requests).
X-RateLimit-RemainingRequests left in the current per-minute window.
X-Regions-CountRegions detected/redacted (on binary redact responses).
X-Review-Recommendedtrue/false — see Detection quality (on binary redact responses).

Entity types

52 PII categories are detected automatically — contact details, financial identifiers (IBAN, cards, crypto), and government / national IDs across the EU & North America. Fetch the live list any time from GET /entities.

Contact & identity
PERSONEMAIL_ADDRESSPHONE_NUMBERLOCATIONSTREET_ADDRESSDATE_TIME
Financial & network
CREDIT_CARDIBAN_CODEABA_ROUTING_NUMBERCRYPTOMEDICAL_LICENSEIP_ADDRESSMAC_ADDRESSURL
United States
US_BANK_NUMBERUS_SSNUS_ITINUS_PASSPORTUS_MBIUS_NPI
Canada
CA_SIN
United Kingdom
UK_NHSUK_NINOUK_PASSPORTUK_DRIVING_LICENCEUK_POSTCODE
France
FR_NIR
Spain
ES_NIFES_NIEES_PASSPORT
Italy
IT_FISCAL_CODEIT_VAT_CODEIT_DRIVER_LICENSEIT_IDENTITY_CARDIT_PASSPORT
Germany
DE_TAX_IDDE_TAX_NUMBERDE_VAT_IDDE_ID_CARDDE_PASSPORTDE_SOCIAL_SECURITYDE_FUEHRERSCHEINDE_HEALTH_INSURANCEDE_LANR
Poland
PL_PESEL
Finland
FI_PERSONAL_IDENTITY_CODE
Sweden
SE_PERSONNUMMERSE_ORGANISATIONSNUMMER
Switzerland
CH_AVS
Netherlands
NL_BSN
Belgium
BE_RRN
Ireland
IE_PPS

Detection accuracy varies by entity type and image quality. We recommend reviewing auto-detected boxes before using the output in production workflows.

Languages

OCR and name/location detection run in the language you pass via the language option (default en). Structured identifiers (IBAN, national IDs, …) are detected regardless of language. Currently available:

en fr de es it

Names are recognised per language by the NLP model — pass the matching language for best accuracy. Street addresses (STREET_ADDRESS) are detected across the common EN, FR, ES and DE layouts (e.g. 1600 Amphitheatre Parkway, 12 Rue de la Paix, Calle Mayor 10, Bahnhofstraße 12).

Rate limits

TierDaily quotaPer-minute limitWatermarkCredits
Free 20 requests 60 / min Yes
Paid Unlimited 60 / min No 1 credit / request

When a limit is exceeded, the API returns 429 Too Many Requests. Retry after the reset window (midnight UTC for daily limits).

Credits are purchased in one-time packs from your dashboard and never expire.

Quick start example (Python)

import requests response = requests.post( "https://privshot.com/api/v1/redact", headers={"X-Api-Key": "ps_your_key_here"}, files={"file": open("screenshot.png", "rb")}, params={"format": "binary"}, ) with open("redacted.png", "wb") as f: f.write(response.content)