New blogMaking an AI Agent You Can Trust With Money

★ India · regex

Regex for GSTIN

A GSTIN for a regular taxpayer is a 2-digit state code, the 10-character PAN, an entity number (1–9 then A–Z) for multiple registrations in the same state, the letter Z, and a check character. The pattern validates the shape and the embedded PAN, not the checksum.

  • Runs in your browser
  • No signup

Try the gstin pattern

Read it in plain English (best-effort)

  • ^start of a line
  • (?:start a group (not captured)
  • 0the character '0'
  • [1-9]one character from: 1–9
  • |or
  • [12]one character from: '1', '2'
  • [0-9]one character from: 0–9
  • |or
  • 3the character '3'
  • [0-8]one character from: 0–8
  • |or
  • 97the text '97'
  • )end of group
  • [A-Z]one character from: A–Z
  • {3}exactly 3 of the previous
  • [ABCFGHJLPT]one character from: 'A', 'B', 'C', 'F', 'G', 'H', …
  • [A-Z]one character from: A–Z
  • [0-9]one character from: 0–9
  • {4}exactly 4 of the previous
  • [A-Z]one character from: A–Z
  • [1-9A-Z]one character from: 1–9, A–Z
  • Zthe character 'Z'
  • [0-9A-Z]one character from: 0–9, A–Z
  • $end of a line

One sample per line works well with the m flag on anchored patterns.

Waiting for a pattern
01

The pattern, piece by piece

/^(?:0[1-9]|[12][0-9]|3[0-8]|97)[A-Z]{3}[ABCFGHJLPT][A-Z][0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$/
Pattern explanation
PartWhat it does
(?:0[1-9]|[12][0-9]|3[0-8]|97)state code 01–38, or 97 for other territory
[A-Z]{3}[ABCFGHJLPT][A-Z][0-9]{4}[A-Z]the embedded PAN
[1-9A-Z]entity number for multiple registrations
Za fixed Z, reserved for future use
[0-9A-Z]$the check character
02

What it accepts and rejects

Every sample below is checked automatically in JavaScript and Python. The tester above is preloaded with all of them, one per line.

Should match
Should match
27AABCU9603R1ZM✓
29AAACB1234C1Z5✓
07AABCS1429B1ZB✓
33AAAFZ9999Z2ZK✓
36AAAPL1234C1ZX✓
10AAATB1234X1ZQ✓
Should not match
Should not match
27AABCU9603R1Z✗
40AABCU9603R1ZM✗
27AABCU9603R0ZM✗
27AABCU9603R1YM✗
27aabcu9603r1zm✗
27AABDU9603R1ZM✗
03

Copy it into your code

RE2-safeNo lookarounds or backreferences, so the same pattern works in Go's RE2 engine and in Rust's regex crate.

const gstinRe = /^(?:0[1-9]|[12][0-9]|3[0-8]|97)[A-Z]{3}[ABCFGHJLPT][A-Z][0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$/;

export function isValidGstin(value) {
  return gstinRe.test(value.trim());
}
04

When not to use regex for this

To confirm a GSTIN is active and get the legal name, use the GST portal's search or an authorised GSP API. Sources disagree on the exact checksum algorithm, so don't rely on a homemade check digit.

05

Questions engineers actually ask

Does every GSTIN contain a PAN?
Regular taxpayers' do. Some special registrations (such as TDS deductors or UN bodies) use other identifiers, which this pattern doesn't cover.
What does the 14th character Z mean?
It's a fixed default character reserved for future use.
What is catastrophic backtracking?
Some patterns, usually nested quantifiers like (a+)+, make a backtracking engine try an exponential number of paths on input that almost matches. The tester stops any run after 300ms, so a bad pattern can't freeze your tab. In production, that same pattern can take down a server (a ReDoS attack).
06

Sources

Formats were checked on 8 November 2026. Rules change; the official issuer wins if it disagrees.

07

More india patterns

08

More from the workbench

Fine print

Tools: on the house.
Engineer: by the hour.

The regex was free. Code that doesn't need one is the upgrade: typed schemas, validated once at the edge, trusted everywhere after.

I'm Himanshu, an AI and full-stack engineer. I build MVPs, AI agents and the growth plumbing around them for early-stage startups.