Your first redaction

Redact PII from a string in about five minutes, over HTTP with Philter or in your own code with Phileas.

There are two ways in. Philter is a redaction service you run with Docker and call over HTTP from any language. Phileas is the library underneath it, which runs in your own process with no service to deploy, for Java, Python, and .NET.

I want to redact using an API

Philter puts the Phileas engine behind a REST API, with stored policies and an audit trail. It suits several applications sharing one policy set, or callers written in any language. Run it with Docker, or launch it from your cloud’s marketplace.

Docker

Start Philter:

export PHILTER_ENCRYPTION_KEY="$(openssl rand -base64 32)"
export PHILTER_API_KEY="sk_$(openssl rand -hex 16)"

docker run -d --name philter -p 8080:8080 \
  -e PHILTER_ENCRYPTION_KEY \
  -e PHILTER_BOOTSTRAP_API_KEY="$PHILTER_API_KEY" \
  -v philter-data:/opt/philter/data \
  philterd/philter:4.0.0

until curl -skf https://localhost:8080/api/health > /dev/null; do sleep 2; done

The bootstrap key is the admin user’s first API key. Keep the encryption key: Philter will not open the data in philter-data with a different one.

Redact something with the built-in default policy:

curl -sk "https://localhost:8080/api/filter" \
  -H "Authorization: Bearer $PHILTER_API_KEY" \
  -H "Content-Type: text/plain" \
  --data-binary "Contact john@example.com or call about SSN 123-45-6789."

The first request loads the person-name model and takes a few seconds. Later requests are fast.

Output:

Contact {{{REDACTED-email-address}}} or call about SSN {{{REDACTED-ssn}}}.

Create your own policy and select it with p:

curl -sk -X POST "https://localhost:8080/api/policies?name=email-only" \
  -H "Authorization: Bearer $PHILTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"identifiers": {"emailAddress": {"emailAddressFilterStrategies": [{"strategy": "REDACT"}]}}}'

curl -sk "https://localhost:8080/api/filter?p=email-only" \
  -H "Authorization: Bearer $PHILTER_API_KEY" \
  -H "Content-Type: text/plain" \
  --data-binary "Contact john@example.com or call about SSN 123-45-6789."

Output:

Contact {{{REDACTED-email-address}}} or call about SSN 123-45-6789.

AWS

Launch Philter from AWS Marketplace on an EC2 instance in your own account. On first boot it generates its own API key, which you read over SSH and use to call the API. Once it is running, Philter needs no outbound internet access.

Follow the AWS quick start →

Philter on AWS: Your machine connects to Philter 4.0 on an EC2 instance in a public subnet of a VPC in your AWS account, through an internet gateway: SSH on port 22 to read the API key, and HTTPS on port 8080 to call the API.

Azure

Launch Philter from Azure Marketplace on a virtual machine in your own account. On first boot it generates its own API key, which you read over SSH and use to call the API. Once it is running, Philter needs no outbound internet access.

Follow the Azure quick start →

Philter on Azure: Your machine connects to Philter 4.0 on a virtual machine in a subnet of a virtual network in your Azure subscription, through a network security group: SSH on port 22 to read the API key, and HTTPS on port 8080 to call the API.

Google Cloud

Launch Philter from Google Cloud Marketplace on a Compute Engine virtual machine in your own account. On first boot it generates its own API key, which you read over SSH and use to call the API. Once it is running, Philter needs no outbound internet access.

Follow the Google Cloud quick start →

Philter on Google Cloud: Your machine connects to Philter 4.0 on a Compute Engine VM in a subnet of a VPC network in your Google Cloud project, through firewall rules: SSH on port 22 to read the API key, and HTTPS on port 8080 to call the API.

Philter serves HTTPS with a self-signed certificate, hence -k. Replace it with your own before production use.

I want to redact in my app

Add Phileas to your application and redact in-process.

Java

Add the dependency:

<dependency>
  <groupId>ai.philterd</groupId>
  <artifactId>phileas</artifactId>
  <version>4.5.0</version>
</dependency>

Redact something. Policies are written in PhiSQL and loaded with Policy.fromPhiSQL:

import ai.philterd.phileas.PhileasConfiguration;
import ai.philterd.phileas.policy.Policy;
import ai.philterd.phileas.model.filtering.TextFilterResult;
import ai.philterd.phileas.services.context.DefaultContextService;
import ai.philterd.phileas.services.disambiguation.vector.InMemoryVectorService;
import ai.philterd.phileas.services.filters.filtering.PlainTextFilterService;

import java.util.Properties;

public class Example {
  public static void main(String[] args) throws Exception {
    final PhileasConfiguration configuration = new PhileasConfiguration(new Properties());

    final PlainTextFilterService filterService = new PlainTextFilterService(
        configuration,
        new DefaultContextService(),
        new InMemoryVectorService(),
        null); // optional HttpClient for PhEye; null uses the default

    final Policy policy = Policy.fromPhiSQL("""
        REDACT EMAIL_ADDRESS WITH REDACT;
        REDACT ZIP_CODE WITH REDACT;
        """);

    final TextFilterResult result = filterService.filter(
        policy, "context", "Email test@example.com, zip 90210.");

    System.out.println(result.getFilteredText());
  }
}

Output:

Email {{{REDACTED-email-address}}}, zip {{{REDACTED-zip-code}}}.

Requires Java 21 or later.

Python

Install:

pip install phileas-redact

Redact something:

from phileas.policy.policy import Policy
from phileas.services.filter_service import FilterService

policy = Policy.from_dict({
    "name": "my-policy",
    "identifiers": {
        "emailAddress": {"emailAddressFilterStrategies": [
            {"strategy": "REDACT", "redactionFormat": "{{{REDACTED-%t}}}"}]},
        "ssn": {"ssnFilterStrategies": [
            {"strategy": "REDACT", "redactionFormat": "{{{REDACTED-%t}}}"}]},
    },
})

result = FilterService().filter(
    policy=policy,
    context="my-context",
    document_id="doc-001",
    text="Contact john@example.com or call about SSN 123-45-6789.",
)

print(result.filtered_text)

for span in result.spans:
    print(f"[{span.filter_type}] -> {span.replacement} "
          f"at {span.character_start}:{span.character_end}")

Output:

Contact {{{REDACTED-email-address}}} or call about SSN {{{REDACTED-ssn}}}.
[email-address] -> {{{REDACTED-email-address}}} at 8:24
[ssn] -> {{{REDACTED-ssn}}} at 43:54

.NET

Install:

dotnet add package Philterd.Phileas

Redact something:

using Phileas.Policy;
using Phileas.Policy.Filters;
using Phileas.Services;

var policy = new Policy
{
    Name = "basic-policy",
    Identifiers = new Identifiers
    {
        Ssn = new Ssn(),
        EmailAddress = new EmailAddress(),
        PhoneNumber = new PhoneNumber()
    }
};

var result = new FilterService().Filter(
    policy,
    context: "session-1",
    piece: 0,
    input: "SSN: 123-45-6789  Email: alice@example.com  Phone: 555-867-5309"
);

Console.WriteLine(result.FilteredText);

Output:

SSN: {{{REDACTED-ssn}}}  Email: {{{REDACTED-email-address}}}  Phone: {{{REDACTED-phone-number}}}

Identifiers default to redaction, so no strategy is specified above.