Classify data fields as PII
The PII field classifier reviews the names in a data schema and assigns each one a likely category: direct PII, indirect PII, or non-PII.
Run — free
It recognizes common signals such as email, passport, date of birth, postal code, device identifier, and ordinary business metrics. Results include a short reason for every decision and category totals, making the output useful for an initial privacy inventory, a schema review, or a repeatable check in a data pipeline. Because it examines names rather than stored values, it is fast and deterministic, but its findings should be confirmed against the meaning and contents of the real dataset.
Start a privacy inventory from the schema
A field list is often the quickest available map of a dataset. Submit the canonical names exactly as they appear in a database, event definition, spreadsheet header, or API contract. The classifier normalizes common styles such as snake case, kebab case, spaces, and camel case before comparing each name with a curated set of signals. Names that indicate an email address, telephone number, full name, government identifier, bank account, payment card, precise address, IP address, or biometric identifier are marked as likely direct PII. These fields can commonly point to a person without needing many additional attributes. The response preserves the original field spelling, gives the classification, and explains the naming signal that produced it. This makes the result easy to join back to a schema export or place in a review worksheet. Submit only field names, not sample records or personal values. An empty list is rejected because it cannot produce a meaningful inventory, and every list item must be a non-empty string.
Interpret indirect PII in context
Indirect PII does not always identify someone on its own, yet it can narrow a population or link activity to a stable person when combined with other fields. The classifier treats names associated with birth date, age, gender, broad location, postal area, device or cookie identifiers, account handles, employment details, and similar attributes as likely indirect PII. That category is intentionally a prompt for contextual review rather than a legal conclusion. A postal code in a national statistics table has a different risk profile from the same field beside a date of birth and an employee identifier. Likewise, a customer identifier may be pseudonymous inside one system while a lookup table makes it directly attributable elsewhere. Review indirect results alongside access controls, join keys, retention periods, population size, and the availability of external datasets. The deterministic rules make repeated scans comparable across schema versions, but they cannot see undocumented semantics or determine whether combinations create singling-out risk.
Use the output as a screening signal, not proof
Names that match no recognized signal are returned as non-PII, which means only that the name itself does not reveal a common privacy cue. A vague field such as value, payload, note, answer, or data could still contain personal information. Conversely, a field named customer_email might contain a test token rather than a real address. Follow the classification with data profiling, documentation review, and input from the people who own the system. In automation, store the result beside the schema version, flag new direct or indirect fields for review, and compare category totals during change control. The output is particularly useful as a lightweight checkpoint before sharing extracts, creating analytics events, or approving a new integration. It should not replace a data protection impact assessment, counsel, or jurisdiction-specific policy. The algorithm uses no network, model, randomness, or current time, so identical input produces identical output. A request through the API costs $0.002, and the returned reasons make rule-driven decisions straightforward to audit.
What you can do with it
Review a database migration
Screen column names before moving tables into a warehouse and route likely PII fields to the privacy owner.
Check analytics event schemas
Catch newly introduced email, device, location, or user identifier fields during event-contract review.
Build a data inventory
Add consistent preliminary PII labels and reasons to a catalog before deeper content inspection.
FAQ
Does this inspect field values?
No. It classifies field names only and should be followed by content inspection when higher confidence is required.
What is direct PII?
Here it means a field name that commonly represents an attribute capable of identifying or directly contacting a person, such as an email address or passport number.
What is indirect PII?
It is an attribute that may identify, single out, or link a person when combined with other data, such as a birth date, postal code, or device identifier.
Can a non-PII result still contain personal data?
Yes. Generic or misleading names can hide personal values, so non-PII means that no common naming signal was detected, not that the contents are safe.
Is the result a legal determination?
No. Privacy definitions vary by jurisdiction and context; use the output as an initial screening result and apply your organization’s policy and legal guidance.
What does an API request cost?
Each API request costs $0.002. The same deterministic rules are suitable for repeatable schema checks.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/security/pii-field-classify \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"field_names":["customer_email","billing_postcode","order_total"]}'const res = await fetch("https://api.kit.forhosting.com/security/pii-field-classify", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"field_names": [
"customer_email",
"billing_postcode",
"order_total"
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/security/pii-field-classify",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"field_names": [
"customer_email",
"billing_postcode",
"order_total"
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/security/pii-field-classify", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"field_names":["customer_email","billing_postcode","order_total"]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"field_names":["customer_email","billing_postcode","order_total"]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/security/pii-field-classify", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"field_names": [
"customer_email",
"billing_postcode",
"order_total"
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "security.pii_field_classify",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_items | 1000 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |