
PII Redactor
hipersoft/pii-redactor
Detect and mask PII (emails, phones, credit cards, SSNs, IPs, IBANs, URLs) in text before it reaches an LLM, with a reversible token map to restore it afterwards.
Total users
2Monthly users
1Total runs
72Per text redacted
$0.002Last rebuilt
Oct 28, 2026Overview
Strip emails, phone numbers, credit cards and other personal data out of your text before it reaches an AI model — then restore it afterwards with a reversible token map. GDPR-friendly redaction for AI, automation and analytics pipelines.
What it does
- Detects and masks PII — email addresses, phone numbers, credit card numbers, US SSNs, IP addresses, IBANs and URLs.
- Reversible tokens — each value becomes a typed token like
[EMAIL_1]or[CREDITCARD_1], so the text stays readable and the structure survives. - One combined token map — a single reversible map (token → original value) is written to the run's key-value store, so a later step can put the real values back.
- Two modes —
mask(sequential typed tokens) orhash(typed tokens with a stable hash). - Privacy by default — the original text is never stored or logged unless you explicitly opt in.
Use cases
- Mask before the LLM — redact prompts before an AI node (OpenAI, Anthropic, etc.), then restore names, emails and numbers in the model's output. Keep raw PII out of third-party models.
- n8n / Make / Zapier flows — drop it in as a step: redact before the AI node, restore after. Great for support-ticket, email and document automations.
- GDPR-friendly logging & analytics — scrub personal data out of text before it lands in logs, datasets or a warehouse.
- Safe sharing — clean transcripts, tickets and messages before handing them to a vendor or teammate.
Input
{
"text": "Contact John at john@acme.com or +1 415 555 0132, card 4111 1111 1111 1111",
"types": ["email", "phone", "creditcard", "ssn", "ip", "iban", "url"],
"mode": "mask",
"includeOriginal": false
}
| Field | Type | Description |
|---|---|---|
text |
string | A single block of text to redact. |
items |
array | An array of strings to redact in bulk (one result row each). |
types |
array | Which PII to catch: email, phone, creditcard, ssn, ip, iban, url. |
mode |
string | mask (tokens like [EMAIL_1]) or hash (tokens with a stable hash). |
includeOriginal |
boolean | Include the original text in each row. Off by default. |
Provide text, items, or both.
Output
Each row is one redacted input:
{
"ok": true,
"redacted": "Contact John at [EMAIL_1] or [PHONE_1], card [CREDITCARD_1]",
"replacements": [
{ "type": "email", "token": "[EMAIL_1]", "value": "john@acme.com" },
{ "type": "phone", "token": "[PHONE_1]", "value": "+1 415 555 0132" },
{ "type": "creditcard", "token": "[CREDITCARD_1]", "value": "4111 1111 1111 1111" }
],
"counts": { "email": 1, "phone": 1, "creditcard": 1 },
"totalReplacements": 3
}
A combined reversible token map is also saved to the run's default key-value store under token-map.json ({ "map": { "[EMAIL_1]": "john@acme.com", ... } }) so a downstream step can restore the originals.
Output schema
| Field | Type | Description |
|---|---|---|
redacted |
string | The text with PII replaced by tokens. |
replacements |
array | Each masked value: type, token and original value. |
counts |
object | Number of matches per PII type. |
totalReplacements |
integer | Total number of masked values in this item. |
original |
string | The original text (only when includeOriginal is on). |
FAQ
Does it call an AI model or any external service? No. Detection is local pattern-matching with light validation (for example a Luhn check on card numbers) — nothing leaves the run.
How do I restore the original values? Use the token-map.json map (token → value) from the key-value store, or the per-row replacements, to swap the tokens back after your AI or automation step.
Can I automate it? Yes — via integrations on the Apify platform (n8n, Make, Zapier and more) and the Apify API.
Notes
Original clean-room implementation.
Input
| Field | Type | Description |
|---|---|---|
textText | string | A single block of text to scan and redact. You can use this instead of, or together with, the Items list. |
itemsItems | array | An array of text strings to scan and redact, one result row per item. Use this for batch processing (e.g. many messages, rows or documents). |
typesPII types to detect | array | Which kinds of PII to detect. Allowed values: email, phone, creditcard, ssn, ip, iban, url. Leave as the default to catch all supported types. Default: ["email", "phone", "creditcard", "ssn", "ip", "iban", "url"] |
modeRedaction mode | string · mask, hash | How to replace detected PII. Mask uses sequential typed tokens like [EMAIL_1]; Hash uses typed tokens with a stable hash of the value. Both are reversible via the token map. Default: "mask" |
includeOriginalInclude original text | boolean | If enabled, the original (unredacted) text is included in each output row. Off by default so raw PII never leaves the run. Default: false |
API
curl -X POST "https://api.apify.com/v2/acts/hipersoft~pii-redactor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"text": "Contact Jane Doe at jane.doe@example.com or +1 202-555-0143. Card 4111 1111 1111 1111."
}'from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("hipersoft/pii-redactor").call(run_input={
"text": "Contact Jane Doe at jane.doe@example.com or +1 202-555-0143. Card 4111 1111 1111 1111."
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('hipersoft/pii-redactor').call({
"text": "Contact Jane Doe at jane.doe@example.com or +1 202-555-0143. Card 4111 1111 1111 1111."
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);Pricing
| Event | Price | Paid plans from |
|---|---|---|
| Text Redacted Charged per text item scanned and redacted. | $0.002 | $0.001 |
You pay only for what the run returns. Set a maximum cost per run and it stops cleanly at that limit.
Related scrapers
Carousell Scraper
Scrape Carousell search listings: title, price, condition, location, seller, photo and URL. Requires your own Carousell app token.
242 runs · 2 users · $0.003 / listing scrapedGoogle Flights Scraper
Scrape flight options from Google Flights by route and date: airline, flight number, departure and arrival times, duration, stops, layovers and price. One-way or round-trip, any cabin and currency. For travel and price monitoring.
216 runs · 4 users · $0.004 / flight scrapedPinterest Scraper
Search Pinterest and scrape pins (title, description, destination link, image, pinner, board, saves), boards and users. Fast. For visual research, e-commerce, trend and marketing analysis.
151 runs · 2 users · $0.0034 / item scrapedGoogle Trends Scraper
Scrape Google Trends for any keyword: interest over time, related and rising queries, and interest by region. Per country and timeframe. For SEO, market and trend research. No setup.
139 runs · 6 users · $0.001 / keyword scrapedAliExpress Product Search Scraper
Search AliExpress by keyword and export one clean row per product — title, sale price, original price, image and product URL. Export to JSON, CSV or Excel.
135 runs · 3 users · $0.003 / product scrapedGoogle Maps Scraper
Search Google Maps and scrape places: name, category, full address, city, coordinates, rating, phone, website, Place ID and map link. Fast browser-free via Google's internal endpoint, no setup. For local lead generation and market research.
130 runs · 2 users · $0.005 / place scrapedSend the site and the fields. We build it and you get it first.