New: Philter One, a redaction box for your office, is coming soon. Learn more →

Contact Us

Tell us about your stack and the privacy problems you're trying to solve. We typically respond within one business day.

Prefer email? support@philterd.ai

Please do not enter PII or PHI in this form. If you need to share an example, use a sanitized one.

← All policies

Healthcare · Philterd

HIPAA Safe Harbor De-Identification

A starting point for HIPAA Safe Harbor de-identification of clinical text per 45 CFR 164.514(b)(2).

v2.0.1 Updated 2026-10-26 Philter >=4.0.0 By Philterd
HIPAASafe HarborPHI45 CFR 164.514de-identification

The policy

The full hipaa-safe-harbor.json file. The same content you’d get by downloading. Copy any part of it, or use the buttons in the hero to grab the whole file.

{
  "config": {
    "splitting": {
      "enabled": false,
      "threshold": 4000
    }
  },
  "ignored": [],
  "ignoredPatterns": [],
  "identifiers": {
    "age": {
      "ageFilterStrategies": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}"
        }
      ]
    },
    "date": {
      "onlyValidDates": true,
      "dateFilterStrategies": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}"
        }
      ]
    },
    "phoneNumber": {
      "phoneNumberFilterStrategies": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}"
        }
      ]
    },
    "emailAddress": {
      "emailAddressFilterStrategies": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}"
        }
      ]
    },
    "ssn": {
      "ssnFilterStrategies": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}"
        }
      ]
    },
    "ipAddress": {
      "ipAddressFilterStrategies": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}"
        }
      ]
    },
    "url": {
      "urlFilterStrategies": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}"
        }
      ]
    },
    "macAddress": {
      "macAddressFilterStrategies": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}"
        }
      ]
    },
    "vin": {
      "vinFilterStrategies": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}"
        }
      ]
    },
    "driversLicense": {
      "driversLicenseFilterStrategies": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}"
        }
      ]
    },
    "passportNumber": {
      "passportNumberFilterStrategies": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}"
        }
      ]
    },
    "zipCode": {
      "priority": 10,
      "zipCodeFilterStrategy": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"036\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"059\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"063\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"102\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"203\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"205\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"369\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"556\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"692\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"790\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"821\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"823\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"830\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"831\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"878\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"879\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"884\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"890\""
        },
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}",
          "condition": "token startswith \"893\""
        },
        {
          "strategy": "TRUNCATE",
          "truncateLeaveCharacters": 3
        }
      ]
    },
    "hospital": {
      "hospitalFilterStrategies": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}"
        }
      ]
    },
    "city": {
      "cityFilterStrategies": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}"
        }
      ]
    },
    "county": {
      "countyFilterStrategies": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}"
        }
      ]
    },
    "streetAddress": {
      "priority": 10,
      "streetAddressFilterStrategies": [
        {
          "strategy": "REDACT",
          "redactionFormat": "{{{REDACTED-%t}}}"
        }
      ]
    },
    "identifiers": [
      {
        "classification": "mrn",
        "pattern": "\\bMRN[\\s:#]*\\d{5,}\\b",
        "caseSensitive": false,
        "identifierFilterStrategies": [
          {
            "strategy": "REDACT",
            "redactionFormat": "{{{REDACTED-MRN}}}"
          }
        ]
      },
      {
        "classification": "account-number",
        "pattern": "\\bACCT[\\s:#]*\\d{6,}\\b",
        "caseSensitive": false,
        "identifierFilterStrategies": [
          {
            "strategy": "REDACT",
            "redactionFormat": "{{{REDACTED-ACCOUNT}}}"
          }
        ]
      }
    ],
    "pheyes": [
      {
        "phEyeConfiguration": {
          "modelPath": "ph-eye-pii-en-small",
          "labels": [
            "name"
          ]
        },
        "phEyeFilterStrategies": [
          {
            "strategy": "REDACT",
            "redactionFormat": "{{{REDACTED-%t}}}"
          }
        ]
      }
    ]
  }
}

Example

Input

Patient John Smith (DOB 1985-04-12, MRN 47291) lives at 1234 Oak Street, Austin, TX 78701. Phone: (555) 123-4567.

Output

Patient {{{REDACTED-name}}} (DOB {{{REDACTED-date}}}, {{{REDACTED-MRN}}}) lives at {{{REDACTED-street-address}}}, {{{REDACTED-city}}}, TX 787**. Phone: {{{REDACTED-phone-number}}}.

Entities this policy acts on

NAMEAGEDATEPHONEEMAILSSNMRNACCOUNTURLIPMAC_ADDRESSVINDRIVERS_LICENSEPASSPORTSTREET_ADDRESSZIPHOSPITALCITYCOUNTY

What this policy does

Designed to redact the text-based identifiers enumerated under the HIPAA Safe Harbor method (45 CFR 164.514(b)(2)). Some require a custom identifier for your deployment, as the table below shows:

#IdentifierHow this policy handles it
1Namespheyes (the deployment’s PhEye model) → REDACT
2Geographic subdivisions smaller than a statestreetAddress, city, county → REDACT; zipCode → truncate to 3 digits, or REDACT for sparsely populated 3-digit areas (see below); hospital → REDACT for hospitals in its dictionary
3All elements of dates (except year) for dates directly related to an individualdate → REDACT (covers admission, discharge, birth, death); age → REDACT (see below)
4Telephone numbersphoneNumber → REDACT
5Fax numbersphoneNumber → REDACT (Philter classifies as phone)
6Email addressesemailAddress → REDACT
7Social Security numbersssn → REDACT
8Medical record numberscustom mrn identifier → REDACT
9Health plan beneficiary numberscustom account-number identifier → REDACT (tune the regex for your plan’s format)
10Account numberscustom account-number identifier → REDACT
11Certificate/license numbersdriversLicense, passportNumber → REDACT; professional licenses need a custom identifier per deployment
12Vehicle identifiers and serial numbersvin → REDACT; license plates need a custom identifier per deployment
13Device identifiers and serial numbersmacAddress → REDACT; serial numbers need a custom identifier per deployment
14Web URLsurl → REDACT
15IP addressesipAddress → REDACT
16Biometric identifiersout of scope for text redaction
17Full-face photosout of scope for text redaction
18Any other unique identifying number, characteristic, or codeadd custom identifiers per deployment

Ages: Safe Harbor requires ages over 89 to be aggregated into a single “90 or older” category. Policy conditions cannot compare an age numerically, so this policy redacts every age it finds. That removes more than Safe Harbor requires.

ZIP codes: Safe Harbor allows the first three digits of a ZIP code only when that 3-digit area has more than 20,000 people. This policy redacts ZIP codes beginning with 036, 059, 063, 102, 203, 205, 369, 556, 692, 790, 821, 823, 830, 831, 878, 879, 884, 890, and 893, which combines the areas at or below that threshold in the 2000 and 2010 Census. Check the list against current Census data before relying on it. Other ZIP codes are truncated to three digits, so 78701 becomes 787**.

streetAddress and zipCode have a higher priority than the other filters, so a house number or ZIP code is not redacted as a driver’s license number.

Hospital names

The hospital filter matches hospitals by name from a dictionary, so it misses hospitals not in that list. To find hospital names in free text, run the PhEye hospitals model (philterd/ph-eye-hospitals) and add a second entry to pheyes:

{
  "phEyeConfiguration": {
    "endpoint": "http://ph-eye-hospitals:5000/",
    "labels": ["hospital"]
  },
  "phEyeFilterStrategies": [
    { "strategy": "REDACT", "redactionFormat": "{{{REDACTED-%t}}}" }
  ]
}

Set endpoint to where the model runs. Philter refuses a policy that names a PhEye endpoint other than PHEYE_ENDPOINT unless an administrator lists it in PHEYE_ALLOWED_ENDPOINTS.

When to customize

  • MRN format. The default regex matches MRN 47291, MRN: 47291, MRN# 47291 with 5+ digits. If your EHR uses a different prefix (e.g., HRN, PTID) or a fixed-width format, update the pattern field in the custom mrn identifier.
  • Account number format. The default \bACCT[\s:#]*\d{6,}\b is illustrative. Replace it with your billing system’s actual account-number pattern.
  • Date treatment. Safe Harbor permits keeping the year for non-individual dates. If you need year-only date generalization (e.g., to preserve temporal ordering for cohort analysis), switch the date strategy from REDACT to a custom replacement format.
  • Identifiers 11, 12, 13, 18. Add custom regex identifiers for any deployment-specific codes (professional license numbers, license plates, insurance member IDs, device serial numbers, internal patient identifiers).

Known limitations

  • The city filter can match ordinary words, such as “Call” or “Driver”, and redact them as cities.
  • Detection is probabilistic. Validate the policy’s output against a sample of your own records before relying on it.

Compliance notes

  • This policy implements the Safe Harbor method under 45 CFR 164.514(b)(2). The alternative, the Expert Determination method under 164.514(b)(1), requires a qualified statistician’s opinion and is out of scope for this policy.
  • Safe Harbor compliance also requires that the covered entity have no actual knowledge that the residual information could identify an individual (164.514(b)(2)(ii)). Automated redaction does not satisfy that requirement on its own; a human reviewer or risk-assessment process is still needed for production deployments.
  • Output dataset is considered de-identified under HIPAA Safe Harbor only after all 18 identifiers are removed and the no-actual-knowledge condition is met.

References

Using this policy with Phileas

The name filter names ph-eye-pii-en-small, the model bundled with Philter 4.0. With Phileas, set its modelPath to the directory of a downloaded copy of the model, philterd/ph-eye-pii-en-small.

Use this policy

Download and load into your running Philter instance:

# Download the policy
curl -O https://raw.githubusercontent.com/philterd/pii-redaction-policies/main/policies/philterd/healthcare/hipaa-safe-harbor.json

# Upload it to Philter as hipaa-safe-harbor
curl -sk -X POST "https://localhost:8080/api/policies?name=hipaa-safe-harbor" \
     -H "Authorization: Bearer $PHILTER_API_KEY" \
     -H "Content-Type: application/json" \
     --data @hipaa-safe-harbor.json

# Redact text with it
curl -sk "https://localhost:8080/api/filter?p=hipaa-safe-harbor" \
     -H "Authorization: Bearer $PHILTER_API_KEY" \
     -H "Content-Type: text/plain" \
     --data-binary "your text here"

For Philter 4.0. No Philter instance yet? The quick start runs one and shows where PHILTER_API_KEY comes from · Want to tune this policy against your data? Talk to the team.