Skip to main content

What is Masking?

Masking is a privacy protection method that partially hides sensitive data by replacing most characters with a masking character (typically *), while keeping a few characters visible for identification purposes. Example:
Input:  "Card: 4532-7562-9102-3456"
Output: "Card: ***************3456"

Input:  "Email: john.doe@company.com"
Output: "Email: joh******************"

How It Works

  1. Detection: Blindfold identifies sensitive entities in your text
  2. Partial Replacement: Most characters are replaced with masking characters
  3. Selective Visibility: A configurable number of characters remain visible
  4. Direction Control: Choose to show characters from the beginning or end

When to Use Masking

Masking is ideal when you need to:

1. Display Payment Information

Show payment methods in user interfaces without exposing full details.
result = client.mask(
    "Card ending in 4532-7562-9102-3456",
    masking_char="*",
    chars_to_show=4,
    from_end=True
)
# Output: "Card ending in ***************3456"
Why this matters:
  • Users can identify their card (last 4 digits)
  • Full card number stays protected
  • PCI-DSS compliant display

2. Show Partial Email Addresses

Display enough to identify the account without exposing the full email.
result = client.mask(
    "Account: john.doe@company.com",
    masking_char="*",
    chars_to_show=3,
    from_end=False
)
# Output: "Account: joh******************"
Use cases:
  • Account recovery confirmation
  • Security notifications
  • Multi-account selection

3. Protect Phone Numbers

Show country code or last digits for verification.
result = client.mask(
    "Contact: +1-555-1234",
    masking_char="X",
    chars_to_show=2,
    from_end=True
)
# Output: "Contact: +1-555-XX34"

4. Display User Information in Admin Panels

Allow admins to identify users without seeing full sensitive data.
user_info = """
Name: John Doe
Email: john.doe@company.com
SSN: 123-45-6789
"""

masked = client.mask(user_info, chars_to_show=4, from_end=True)
# Admins see partially masked information

When NOT to Use Masking

Masking is not suitable when:

1. You Need to Restore Original Data

Masking is irreversible. Use Tokenization instead.
# Bad - can't restore
masked = client.mask("john@example.com")
# No way to get "john@example.com" back

# Good - use tokenization
protected = client.tokenize("john@example.com")
original = client.detokenize(protected.text, protected.mapping)

2. You Need Complete Removal

If no part should be visible, use Redaction.
# Bad - still shows part of SSN
masked = client.mask("SSN: 123-45-6789")
# Output: "SSN: **********89"

# Good - complete removal
redacted = client.redact("SSN: 123-45-6789")
# Output: "SSN: <US_SSN>"

3. Data is for Processing (Not Display)

For data processing by systems, use Tokenization or Redaction.
# Bad - processing masked data is unreliable
masked = client.mask(api_key)
send_to_api(masked.text)  # API won't work with ***key

# Good - tokenize for processing
protected = client.tokenize(api_key)

Key Features

Configurable Visibility

Choose how many characters to show (1-10+)

Direction Control

Show characters from start or end

Custom Mask Character

Use *, X, #, or any character

Multiple Entity Types

Works with emails, cards, SSNs, phones, etc.

Quick Start

from blindfold import Blindfold

client = Blindfold(api_key="your-api-key")

# Basic masking (show last 4)
result = client.mask(
    text="Credit card: 4532-7562-9102-3456",
    masking_char="*",
    chars_to_show=4,
    from_end=True
)
print(result.text)
# "Credit card: ***************3456"

# Custom mask character
result = client.mask(
    text="SSN: 123-45-6789",
    masking_char="X",
    chars_to_show=4,
    from_end=True
)
print(result.text)
# "SSN: XXXXXXX6789"

# Show from beginning
result = client.mask(
    text="Email: john.doe@company.com",
    masking_char="*",
    chars_to_show=3,
    from_end=False
)
print(result.text)
# "Email: joh******************"

Configuration Options

Masking Character

Choose which character to use for masking:
# Asterisks (default)
client.mask(text, masking_char="*")  # ***3456

# X marks
client.mask(text, masking_char="X")  # XXX3456

# Dashes
client.mask(text, masking_char="-")  # ---3456

# Dots
client.mask(text, masking_char=".")  # ...3456

Characters to Show

Control how many characters remain visible:
# Show last 4 (common for cards)
client.mask(text, chars_to_show=4)  # ***************3456

# Show last 2 (for phone numbers)
client.mask(text, chars_to_show=2)  # *********34

# Show first 3 (for emails)
client.mask(text, chars_to_show=3, from_end=False)  # joh***************

Direction

Choose to show characters from the start or end:
# Show from end (default) - good for cards, phones
client.mask(text, from_end=True)  # ***3456

# Show from start - good for emails, names
client.mask(text, from_end=False)  # joh***

Filter Entity Types

Only mask specific types of data:
result = client.mask(
    "Card: 4532-7562-9102-3456, Email: john@example.com",
    entities=["CREDIT_CARD"],  # Only mask cards
    chars_to_show=4,
    from_end=True
)
# Output: "Card: ***************3456, Email: john@example.com"

Common Patterns

Payment Card Display

Standard pattern for showing payment cards:
def display_payment_method(card_number):
    """Display card with last 4 digits visible"""
    result = client.mask(
        f"Card: {card_number}",
        masking_char="*",
        chars_to_show=4,
        from_end=True
    )
    return result.text

# Usage
display_payment_method("4532-7562-9102-3456")
# "Card: ***************3456"

Email Display

Show beginning of email for identification:
def display_email(email):
    """Show first 3 characters of email"""
    result = client.mask(
        email,
        masking_char="*",
        chars_to_show=3,
        from_end=False
    )
    return result.text

# Usage
display_email("john.doe@company.com")
# "joh******************"

Phone Number Display

Show last 2 or 4 digits:
def display_phone(phone):
    """Show last 2 digits of phone"""
    result = client.mask(
        phone,
        masking_char="X",
        chars_to_show=2,
        from_end=True
    )
    return result.text

# Usage
display_phone("+1-555-1234")
# "+1-555-XX34"

Common Use Cases

Show saved payment methods to customers:
# Display stored cards
cards = [
    "4532-7562-9102-3456",
    "5425-2334-3010-9903"
]

for card in cards:
    masked = client.mask(card, chars_to_show=4, from_end=True)
    print(f"Card ending in {masked.text[-4:]}")
Benefits: Users can identify their cards, PCI compliance maintained
Confirm user identity by showing partial email:
def show_recovery_email(email):
    masked = client.mask(
        email,
        chars_to_show=3,
        from_end=False
    )
    return f"We'll send a code to {masked.text}"

show_recovery_email("john.doe@company.com")
# "We'll send a code to joh******************"
Benefits: User knows which account, email address not exposed
Show user information to admins without full PII:
def display_user_info(user_data):
    masked = client.mask(
        user_data,
        chars_to_show=4,
        from_end=True
    )
    return masked.text

user = "Email: john@example.com, Phone: +1-555-1234"
print(display_user_info(user))
# Shows partially masked information
Benefits: Admins can identify users, reduced PII exposure
Notify users about security events without exposing full details:
def send_security_alert(phone_number):
    masked = client.mask(
        phone_number,
        chars_to_show=2,
        from_end=True
    )
    return f"Security alert sent to phone ending in {masked.text[-2:]}"

send_security_alert("+1-555-1234")
# "Security alert sent to phone ending in 34"
Benefits: User can verify it’s their number, privacy maintained

Best Practices

1. Follow Industry Standards

Use established patterns for different data types:
# Credit cards: Show last 4
client.mask(card, chars_to_show=4, from_end=True)

# Emails: Show first 3
client.mask(email, chars_to_show=3, from_end=False)

# Phones: Show last 2-4
client.mask(phone, chars_to_show=2, from_end=True)

# SSNs: Show last 4
client.mask(ssn, chars_to_show=4, from_end=True)

2. Balance Security and Usability

Show enough for identification, not more:
# Good - enough to identify
client.mask(card, chars_to_show=4)  # ***3456

# Risky - too much visible
client.mask(card, chars_to_show=12)  # 4532-7562-9103456

3. Use Consistent Masking

Be consistent across your application:
# Create a helper function
def mask_pii(text, entity_type):
    if entity_type == "card":
        return client.mask(text, chars_to_show=4, from_end=True)
    elif entity_type == "email":
        return client.mask(text, chars_to_show=3, from_end=False)
    # etc.

4. Document Your Masking Rules

Make it clear what’s shown and what’s hidden:
# Add tooltips or help text
"Card ending in ***3456 (only last 4 digits shown)"
"Email: joh*** (only first 3 characters shown)"

Security Considerations

Masking reduces but does not eliminate risk. Consider:
  • Not reversible: Once masked, data cannot be restored
  • Partial exposure: Some characters remain visible
  • Pattern recognition: Repeated masking may reveal patterns
  • Compliance: Check if masking meets your regulatory requirements

Learn More

Python SDK

Full Python SDK documentation

JavaScript SDK

Complete JavaScript guide

Java SDK

Sync and async Java client

REST API

HTTP API reference for /mask

Examples

Practical integration examples

Compare with Other Methods

Tokenization

Reversible replacement with tokens

Redaction

Complete permanent removal

Hashing

Deterministic identifiers

Encryption

AES encryption with key