Localized identifiers¶
National identifiers follow country-specific formats, so each one gets its own anonymizer. Both scan free-form text, mask every identifier they find, and return the cleaned content.
anonymizer = UsaIdentifierAnonymizer(text)
cleaned = anonymizer.anonymize() # also available as anonymizer.cleaned_content
United States — Social Security Numbers¶
UsaIdentifierAnonymizer masks the first five digits and keeps the last four, preserving
whichever separator the text uses.
from shadow_data.l10n.usa import UsaIdentifierAnonymizer
text = "Billy's SSN is 479-92-5042. Please make sure it's anonymized."
print(UsaIdentifierAnonymizer(text).anonymize())
Dashes, spaces, and no separator at all are all recognized, and multiple numbers in the same text are handled:
from shadow_data.l10n.usa import UsaIdentifierAnonymizer
print(UsaIdentifierAnonymizer('SSNs are 123-45-6789, 987 65 4321 and 123456789.').anonymize())
Anything that is not a complete SSN is left untouched, including partial numbers
(123-45) and longer digit runs (1234-56-7890).
Brazil — CPF and CNPJ¶
BrazilIdentifierAnonymizer handles both the individual (CPF, 11 digits) and corporate
(CNPJ, 14 digits) tax IDs. Separators are preserved and only the first two digits stay
visible.
from shadow_data.l10n.brazil import BrazilIdentifierAnonymizer
print(BrazilIdentifierAnonymizer('806.846.761-09').anonymize())
print(BrazilIdentifierAnonymizer('26.283.050/0001-17').anonymize())
Bare digits work too, and identifiers are found inside sentences:
from shadow_data.l10n.brazil import BrazilIdentifierAnonymizer
text = 'O CPF do titular e 806.846.761-09 e o CNPJ da empresa e 26.283.050/0001-17.'
print(BrazilIdentifierAnonymizer(text).anonymize())
CNPJ is matched before CPF, so the trailing 11 digits of a CNPJ are never mistaken for a CPF. Content with no identifier is returned unchanged.
No checksum validation
Both anonymizers match on shape, not on the CPF/CNPJ/SSN check digits. A well-formed but invalid number will still be masked — which is the safe direction to err in.
Deprecated aliases¶
Both modules used to export a class called IdentifierAnonymizer, which meant importing
both required aliasing. The name still works and points at the new class:
from shadow_data.l10n.brazil import IdentifierAnonymizer # -> BrazilIdentifierAnonymizer
from shadow_data.l10n.usa import IdentifierAnonymizer # -> UsaIdentifierAnonymizer
It will be removed in 2.0. Prefer BrazilIdentifierAnonymizer and
UsaIdentifierAnonymizer.
Adding a country¶
Both classes extend ClearIdentifier, which takes the content in its constructor and
requires an anonymize() method returning the cleaned string: