India · PAN validation
Catch a malformed PAN before it reaches your books.
A PAN has a fixed structure: five letters, four digits, one letter, with the fourth letter giving the holder type and the fifth the name initial. KYCVerify validates all of it and, when the card is photographed, reads it back by OCR to compare.
- characters, validated position by position
- 10
- holder types recognised from the fourth letter
- 10
- government lookups: structural validation only
- 0
What it checks
PAN, check by check.
Each rule below is what the engine actually runs. The result is written as a pan check with its score and warnings.
Format
[A-Z]{3}[ABCFGHJLPT][A-Z][0-9]{4}[A-Z], after upper-casing and removing whitespace.Holder type
The fourth character identifies an individual, company, firm, trust, HUF, government body and others. A non-individual PAN sends the PAN step to review as
pan_not_individual.Name initial
For individuals the fifth character is the surname initial; for others, the entity-name initial. A mismatch with the supplied name is a warning.
Card cross-check
With a card image, the PAN and name are read by OCR and compared with what the person typed.
Try it
Type a PAN, read it position by position.
Ten characters, five rules. The validator below is the engine's, run on your keyboard input: structure, holder type, and the name initial with honorifics stripped.
- The rules are ported line for line from the Rust engine, and the page names the file.
- Everything runs locally in this tab. No request is made while you type.
- Reset puts the example back; nothing is saved.
PAN structure explainer
Spaces are removed and letters upper-cased first.
Honorifics such as Mr, Smt and M/s are ignored.
Position by position
- ABCSeriesvalid
- PHoldervalid
- SInitialvalid
- 1234Numbervalid
- FLettervalid
The holder letter is one of P, C, H, F, A, T, B, L, J, G. For an individual (P) the fifth letter is the surname initial; for a company, firm or trust it is the entity name's initial.
Valid structure
{
"normalized": "ABCPS1234F",
"valid_format": true,
"holder_type": "individual",
"name_initial_match": true,
"issues": [],
"government_lookup": false,
"note": "Structural validation only: format, holder type and name initial. No government database (NSDL / Protean / Income Tax Department) lookup was performed."
}A structurally valid PAN can still be unissued or someone else's. KYCVerify makes no lookup against the Income Tax Department, and every response says so.
Logic ported from backend/crates/kyc-india/src/pan.rs. Nothing you type leaves this page.
How it works
What happens, in order.
- 1
Enter
The person types their PAN and name, and optionally photographs the card.
- 2
Validate
Structure, holder type and initial are checked; the card image, if any, is read and compared.
- 3
Record
A
pancheck is written with the validation detail and a note that no government lookup was made.
Configuration
The workflow keys and their defaults.
"pan": { "enabled": true, "require_card_image": false }| Key | Default | Meaning |
|---|---|---|
| require_card_image | false | Ask for a photo of the PAN card as well as the number. |
Reference
The fourth letter says who holds it.
| Letter | Holder type | Fifth letter is |
|---|---|---|
| P | Individual | Surname initial |
| C | Company | Entity name initial |
| H | Hindu undivided family | Surname or name initial |
| F | Firm or LLP | Entity name initial |
| A | Association of persons | Entity name initial |
| T | Trust | Entity name initial |
| B | Body of individuals | Entity name initial |
| L | Local authority | Entity name initial |
| J | Artificial juridical person | Entity name initial |
| G | Government | Entity name initial |
Reasons and warnings
Exact codes, as they appear in the check's data and warnings, so you can branch on them.
| Code | Outcome | When |
|---|---|---|
| pan_invalid_format | failed | Not AAAAA9999A, or the fourth letter is not a holder type. The person may correct it and retry. |
| pan_not_individual | review | The PAN belongs to a company, firm, trust or other non-individual holder. |
| pan_name_mismatch | review | The fifth letter, or the name on the photographed card, does not match the holder's name. |
| pan_card_mismatch | review | The PAN printed on the photographed card differs from the one typed. |
| pan_card_unread | review | The card image could not be read, when require_card_image is on. |
API
Validate a PAN in one call.
POST /v1/checks/pan with the PAN and, optionally, the holder's name. The response always carries government_lookup: false.
Validate a PAN in one call.
curl -X POST https://kycverify.me/api/v1/checks/pan \
-H "x-api-key: $KYC_API_KEY" \
-H "content-type: application/json" \
-d '{
"pan": "ABCPS1234F",
"name": "Rahul Kumar Sharma"
}'200 OK
{
"normalized": "ABCPS1234F",
"valid_format": true,
"holder_type": "individual",
"name_initial_match": true,
"issues": [],
"government_lookup": false,
"note": "Structural validation only: format, holder type and name initial. No government database (NSDL / Protean / Income Tax Department) lookup was performed."
}Limits
What it does not do.
Stated up front, so you can decide what to pair it with.
- No lookup against the Income Tax Department, NSDL or Protean: that requires a licensed provider. A structurally valid PAN may not exist or may belong to someone else.
- Pair PAN with a document or Aadhaar step and face match when you need to bind the PAN to a present person.
FAQ
PAN: questions.
Can I validate a PAN from my backend?
Yes. POST /v1/checks/pan with { pan, name? } returns the structural validation.
Why not verify against the government database?
Because that requires a licence KYCVerify does not have and does not pretend to. The check data states plainly that no lookup was made.
Try it in the sandbox today.
Every check is available from the first sign-up, with test keys and a default workflow. Talk to us when you are ready to verify real people.