How to anonymize personal data in json api mock responses
- Step 1Capture a real response — Use Postman, curl, or DevTools to grab a complete production API response, then save it as a JSON file (under 2 MB for free tier).
- Step 2Drop it in — Add the JSON file to the dropzone. One response per run; there is no batch upload.
- Step 3Tune the PII terms — Keep the defaults and add API-specific keys like
customerEmail, accessToken, deviceId. Matching is case-insensitive substring, so be specific to avoid scrubbing keys you want to keep. - Step 4Pick a strategy — Choose hash to keep id relationships across the mock, fake for human-readable example data, mask to keep shapes, or remove to delete sensitive fields outright.
- Step 5Keep Deep on — Leave Deep enabled so PII nested inside the response envelope and inside arrays of objects is scrubbed.
- Step 6Save as your mock — Download the
.anon.json(or Copy) and paste it into a Postman example, an MSW handler return value, or a json-server fixture. Re-scan for free-text PII before committing.
Strategy fit for mock data
Choose by what your mock consumers expect.
| Mock need | Strategy | Keeps id relationships? | Looks realistic? |
|---|---|---|---|
| Stable mock identities across objects | hash | Yes | No (hex tokens) |
| Readable example data | fake | No | Sort of (userN@example.com) |
| Same shape as production | mask | Value-stable only | Yes (length preserved) |
| Hide secrets entirely | remove | n/a | Field gone |
Typical API response keys and detection
Substring match against your term list.
| Response key | Default term that catches it | Detected? |
|---|---|---|
| data.user.email | Yes (with Deep on) | |
| data.user.phoneNumber | phone | Yes |
| meta.clientIp | ip | Yes |
| data.message (free text with an email inside) | — | No (value not scanned) |
| data.accessToken | (add 'token' or 'accessToken') | Only if added |
Tier limits for captured responses
Single file per run.
| Tier | Max file | Batch |
|---|---|---|
| Free | 2 MB | 1 |
| Pro | 100 MB | 10 |
| Developer | 5 GB | unlimited |
Cookbook
Turning captured production responses into mocks that are safe to share and still structurally faithful.
Scrub a nested REST envelope
ExampleDeep on reaches PII inside the data envelope while leaving status/meta intact.
Strategy: mask · Deep: on
Input:
{ "status": "ok", "data": { "user": { "name": "Linus", "email": "linus@x.com" } } }
Output:
{ "status": "ok", "data": { "user": { "name": "Li**us", "email": "li***@x.com" } } }Hash to keep mock id relationships
ExampleThe user's id appears again inside an embedded orders array. hash keeps both equal so the mock's relationships hold.
PII terms: email, userId
Strategy: hash · Deep: on
Input:
{ "user": { "userId": "u_88" },
"orders": [ { "userId": "u_88" } ] }
Output:
{ "user": { "userId": "3df90a17" },
"orders": [ { "userId": "3df90a17" } ] }Remove an auth token from the response
ExampleAdd accessToken to the terms and use remove so the mock never leaks a credential shape.
PII terms: email, accessToken
Strategy: remove
Input:
{ "accessToken": "sk_live_abc", "user": { "email": "a@x.com" } }
Output:
{ "user": {} } (email removed too — it matched and was removed)PII hidden in a free-text field is NOT scrubbed
ExampleThe tool matches keys, never values. An email inside a message body survives — handle it separately.
Strategy: hash
Input:
{ "message": "Contact me at real@person.com", "email": "a@x.com" }
Output:
{ "message": "Contact me at real@person.com", ← still there
"email": "7c4e1aa9" }Fake for a readable Postman example
Examplefake gives placeholder-but-readable values; remember they are sequential, not stable across files.
Strategy: fake
Input:
[ { "name": "Ada", "email": "ada@x.com" },
{ "name": "Bo", "email": "bo@x.com" } ]
Output:
[ { "name": "User 1", "email": "user1@example.com" },
{ "name": "User 2", "email": "user2@example.com" } ]Errors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
Large captured response over 2 MB
BlockedFree tier caps files at 2 MB. Trim the response to the records you need or upgrade to Pro (100 MB).
Response copied as a JS object literal
Parse errorPasting a logged object with unquoted keys or trailing commas fails JSON.parse. Convert it to valid JSON first with json-format-fixer.
PII in a free-text body
Not detectedThe tool only matches keys, so an email/phone inside a message or notes string survives. Add the whole key and remove/fake it, or strip it with json-key-filter.
Deep off on a nested envelope
SurvivesWith Deep off, only top-level keys are scrubbed; PII inside data.user is left intact. Keep Deep on for API payloads.
Token key not in the list
LeaksAuth tokens are not in the defaults. If accessToken/apiKey is in your response and not added to the terms, it is copied verbatim. Add it and use remove.
fake expected to be stable across two mock files
Cautionfake restarts its counter every run and per file, so the 'same' user gets user1@… in one file and a different value in another. Use hash for stable cross-file identities.
remove fields a client requires
May break clientIf your client code requires a field, removing it makes the mock fail validation. Use mask/hash to keep the key present.
Numeric id becomes a string
Type changeValues are stringified before hashing, so a numeric id key turns into a string token. If your mock asserts on type, exclude ids from the term list.
Stat shows 0 fields
Check termsA zero count means no key name matched a term — verify the response's key names actually contain your terms (case-insensitive substring), and that Deep is on for nested keys.
Frequently asked questions
Will the anonymized mock still test the real code paths?
Yes for mask/hash/fake — they keep all keys and nesting, so your client parses the same structure. remove deletes keys, which can change the path if the client requires them.
How is PII detected in an API response?
By key name only, via case-insensitive substring match against your term list (defaults email, name, phone, address, ssn, dob, birthdate, ip, password). Values are never inspected.
Can I keep ids consistent across user and orders objects?
Yes — add the id key to the term list and use hash. The deterministic token is identical wherever the same source id appears.
Does the captured response get uploaded?
No. Everything runs in your browser. The real response is never transmitted to JAD Apps.
How do I handle PII embedded in free-text fields?
The tool can't detect it (keys only). Add the whole field key (e.g. message) and use remove or fake to replace its value, or drop the field with json-key-filter.
Can I scrub several captured responses at once?
No — one file per run. There is no multi-file batch in this tool.
What does fake generate for mock data?
Sequential placeholders: email keys → userN@example.com, name keys → 'User N', phone → +1-555-NNNN, ip → 192.168.x.y, others → [REDACTED-N]. They are not realistic faker-style names.
Is the hash cryptographically strong?
No. It's a fast 32-bit, 8-character hex token — fine for de-identifying mocks and keeping joins, not a SHA-style digest despite the UI hint.
What file size can I process?
2 MB on Free, 100 MB on Pro, 5 GB on Developer. No row gate.
Can I control output formatting?
Output is 2-space pretty JSON; there is no indent control. Minify it for a compact fixture with json-minifier.
Should I anonymize a real response or generate a fake one?
Anonymize the real one when structural fidelity matters. Use json-mock-generator when you just need synthetic records with a fixed shape.
How do I confirm nothing was missed?
Eyeball the output and search for your original domain/area codes, and inspect free-text fields manually since they are never scanned. json-tree-viewer helps you scan a large nested mock.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.