Regex for PAN Card Validation in JavaScript and Python
Every Indian Permanent Account Number (PAN) follows a strict 10-character format defined by the Income Tax Department. Because the structure never changes, a regular expression is the fastest and most reliable way to validate PAN input in a signup form, KYC flow, or backend API before you spend an API call on a real verification service. This guide breaks down the PAN format, gives you a copy-paste regex for JavaScript and Python, and covers the edge cases that trip up naive implementations.
Understanding the PAN format
A PAN is always 10 characters long and follows the pattern AAAAA9999A. Each part of the string has a defined meaning:
- First 5 characters — uppercase letters (A-Z). The 4th letter indicates the holder type (P for individual, C for company, H for HUF, and so on).
- Next 4 characters — digits (0-9), a sequential number unique to that letter series.
- Last character — an uppercase alphabetic check character.
Because every PAN follows this exact 5-4-1 structure with no separators, spaces, or hyphens, the regex is short and unambiguous.
The PAN regex pattern
^[A-Z]{5}[0-9]{4}[A-Z]{1}$This anchors the match to the full string with ^ and $, so partial matches inside a longer string are rejected. A valid example is ABCDE1234F.
JavaScript example
Always normalize the input to uppercase and trim whitespace before testing it against the regex — users frequently paste PAN numbers with extra spaces or in lowercase.
function isValidPAN(pan) {
const panRegex = /^[A-Z]{5}[0-9]{4}[A-Z]{1}$/;
const normalized = pan.trim().toUpperCase();
return panRegex.test(normalized);
}
console.log(isValidPAN("abcde1234f")); // true
console.log(isValidPAN("ABCDE12345")); // false - last char must be a letter
console.log(isValidPAN("ABCD1234F")); // false - only 4 letters at startPython example
import re
PAN_REGEX = re.compile(r"^[A-Z]{5}[0-9]{4}[A-Z]{1}$")
def is_valid_pan(pan: str) -> bool:
normalized = pan.strip().upper()
return bool(PAN_REGEX.match(normalized))
print(is_valid_pan("abcde1234f")) # True
print(is_valid_pan("ABCDE123F")) # False - only 3 digitsCommon mistakes to avoid
- Skipping the
^and$anchors — without them, a regex engine may match a valid 10-character substring inside a longer, invalid string. - Forgetting to uppercase user input, which causes valid lowercase PANs to fail validation.
- Treating a regex match as proof the PAN is genuine. Format validation only checks structure — use it as a first-line client-side check, then confirm with a real verification API server-side for anything KYC-related.
- Allowing spaces or hyphens in the pattern. Real PAN numbers never contain separators, so building that flexibility into the regex just weakens validation.
Frequently Asked Questions
The standard regex is ^[A-Z]{5}[0-9]{4}[A-Z]{1}$. It matches five uppercase letters, four digits, and one uppercase letter, which is the fixed structure the Income Tax Department uses for every PAN.
No. Regex only confirms the PAN follows the correct format (10 characters in the AAAAA9999A pattern). It cannot confirm the PAN was actually issued or belongs to a real taxpayer — that requires the official NSDL or Income Tax e-filing verification API.
PAN numbers are always uppercase in official records, but user input is often lowercase or mixed case. Convert the input to uppercase with toUpperCase() (JavaScript) or .upper() (Python) before running the regex, rather than adding a case-insensitive flag.