common.skipToContent

API Reference

Complete REST API documentation for anonymize.today

The anonymize.today API enables programmatic access to PII detection and anonymization. All endpoints use JSON and require authentication via Bearer tokens.


Base URL

https://anonymize.today/api

All API endpoints are relative to this base URL. For example, the analyze endpoint is https://anonymize.today/api/presidio/analyze.


Authentication

All authenticated endpoints require a Bearer token in the Authorization header:

Authorization: Bearer YOUR_API_TOKEN

Getting an API Token

  1. Sign in to your anonymize.today account
  2. Go to Settings → Account → API Tokens
  3. Click Generate New Token
  4. Copy and securely store your token (it won't be shown again)

Security Note

Never expose your API token in client-side code or public repositories. Use environment variables and server-side requests.

Token in Requests

TypeScript

const response = await fetch('https://anonymize.today/api/presidio/analyze', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.ANONYMIZE_API_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ text, entities }),
});

Python

import os
import requests

headers = {
    "Authorization": f"Bearer {os.environ['ANONYMIZE_API_TOKEN']}",
    "Content-Type": "application/json"
}

response = requests.post(
    "https://anonymize.today/api/presidio/analyze",
    headers=headers,
    json={"text": text, "entities": entities}
)

cURL

curl -X POST https://anonymize.today/api/presidio/analyze \
  -H "Authorization: Bearer $ANONYMIZE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"text": "John Doe works at Acme Corp", "entities": ["PERSON", "ORGANIZATION"]}'

Rate Limits

Endpoint TypeRate LimitBurst
Authentication3 requests/second5 requests
Analysis & Anonymization30 requests/second50 requests
Presets & Settings10 requests/second20 requests

When rate limited, the API returns 429 Too Many Requests with a Retry-After header indicating when you can retry.


Core Endpoints

Analyze Text

Detect PII entities in text. Returns positions and types of detected entities.

Anonymize Text

Anonymize detected PII entities using various operators.

Deanonymize Text

Restore encrypted entities to their original values using the same encryption key.


Anonymization Operators

OperatorDescriptionReversibleExample
replaceReplace with placeholderNoJohn → [PERSON]
maskPartially mask charactersNojohn@email.com → j***@email.com
redactRemove completelyNoJohn → (empty)
hashOne-way SHA-256 hashNoJohn → a3f2b1c4...
encryptAES-256-GCM encryptionYesJohn → [ENC:...]

Operator Configurations

// Replace operator
{ "type": "replace", "new_value": "[PERSON]" }

// Mask operator
{
  "type": "mask",
  "masking_char": "*",
  "chars_to_mask": 5,
  "from_end": false
}

// Hash operator
{ "type": "hash", "hash_type": "sha256" }

// Encrypt operator (requires encryption key in user settings)
{ "type": "encrypt" }

// Redact operator
{ "type": "redact" }

Presets API


Entity Types

anonymize.today supports 256 entity types across 10 categories:

Personal

PERSON, EMAIL_ADDRESS, PHONE_NUMBER

Financial

CREDIT_CARD, IBAN_CODE, SWIFT_CODE, CRYPTO

Location

LOCATION, ADDRESS, COORDINATES

Government

SSN, PASSPORT, DRIVER_LICENSE, NATIONAL_ID

Contact

URL, DOMAIN_NAME

Technical

IP_ADDRESS, MAC_ADDRESS

Temporal

DATE_TIME, AGE

Organizational

ORGANIZATION, JOB_TITLE

Medical

MEDICAL_LICENSE, HEALTH_ID

Custom

User-defined patterns

See the complete list of entity types in the Presets documentation.


Supported Languages

The API supports 27 languages for PII recognition:

CodeLanguageEngine
enEnglishspaCy
deGermanspaCy
esSpanishspaCy
frFrenchspaCy
itItalianspaCy
ptPortuguesespaCy
nlDutchspaCy
plPolishspaCy
ruRussianspaCy
jaJapanesespaCy
zhChinesespaCy
koKoreanspaCy
arArabicTransformer
hiHindiTransformer
trTurkishTransformer

Additional languages: Romanian, Greek, Croatian, Slovenian, Macedonian, Swedish, Danish, Norwegian, Finnish, Ukrainian, Lithuanian, Catalan


Error Handling

The API uses standard HTTP status codes:

StatusMeaningDescription
200OKRequest succeeded
201CreatedResource created successfully
400Bad RequestInvalid request body or parameters
401UnauthorizedMissing or invalid API token
402Payment RequiredInsufficient tokens
403ForbiddenAccess denied to resource
404Not FoundResource not found
429Too Many RequestsRate limit exceeded
500Internal ErrorServer error

Error Response Format

{
  "error": {
    "code": "INSUFFICIENT_TOKENS",
    "message": "You need 5 tokens but only have 2 remaining",
    "details": {
      "required": 5,
      "available": 2
    }
  }
}

Complete Examples

TypeScript/Node.js

import fetch from 'node-fetch';

const API_BASE = 'https://anonymize.today/api';
const API_TOKEN = process.env.ANONYMIZE_API_TOKEN;

async function analyzeAndAnonymize(text: string) {
  // Step 1: Analyze
  const analyzeResponse = await fetch(`${API_BASE}/presidio/analyze`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_TOKEN}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      text,
      entities: ['PERSON', 'EMAIL_ADDRESS', 'PHONE_NUMBER'],
      language: 'en',
    }),
  });

  const { results } = await analyzeResponse.json();

  if (results.length === 0) {
    return { text, anonymized: false };
  }

  // Step 2: Anonymize
  const anonymizeResponse = await fetch(`${API_BASE}/presidio/anonymize`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_TOKEN}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      text,
      analyzer_results: results,
      anonymizers: {
        DEFAULT: { type: 'replace', new_value: '[REDACTED]' },
      },
    }),
  });

  return anonymizeResponse.json();
}

// Usage
const result = await analyzeAndAnonymize('Contact John Doe at john@example.com');
console.log(result.text); // "Contact [REDACTED] at [REDACTED]"

Python

import os
import requests

API_BASE = "https://anonymize.today/api"
API_TOKEN = os.environ["ANONYMIZE_API_TOKEN"]

def analyze_and_anonymize(text: str) -> dict:
    headers = {
        "Authorization": f"Bearer {API_TOKEN}",
        "Content-Type": "application/json"
    }

    # Step 1: Analyze
    analyze_response = requests.post(
        f"{API_BASE}/presidio/analyze",
        headers=headers,
        json={
            "text": text,
            "entities": ["PERSON", "EMAIL_ADDRESS", "PHONE_NUMBER"],
            "language": "en"
        }
    )
    results = analyze_response.json()["results"]

    if not results:
        return {"text": text, "anonymized": False}

    # Step 2: Anonymize
    anonymize_response = requests.post(
        f"{API_BASE}/presidio/anonymize",
        headers=headers,
        json={
            "text": text,
            "analyzer_results": results,
            "anonymizers": {
                "DEFAULT": {"type": "replace", "new_value": "[REDACTED]"}
            }
        }
    )

    return anonymize_response.json()

# Usage
result = analyze_and_anonymize("Contact John Doe at john@example.com")
print(result["text"])  # "Contact [REDACTED] at [REDACTED]"

Related Documentation

Last Updated: February 2026