Skip to main content
Thirdwatchthirdwatch
Compliance & registries

Verify Indian GST Numbers at Scale (2026 Guide)

Verify Indian GSTIN numbers at scale using Thirdwatch. Bulk supplier compliance + KYB workflows + India vendor due diligence recipes.

Apr 28, 2026 · 5 min read · 1,030 words
See the scraper →

Thirdwatch's GST Verification Scraper validates GSTIN format and checksum, then returns public indexed registration metadata with explicit provenance. Built for India compliance teams, finance operations, KYB workflows, and vendor due-diligence pipelines.

Why automate GSTIN verification at scale

Indian supplier compliance is increasingly automation-dependent. A vendor identifier can be well-shaped yet still contain a wrong check digit, and registration metadata can change after onboarding. For finance teams managing hundreds or thousands of India suppliers, a repeatable validation and snapshot process is safer than manual copy-paste checks.

The job-to-be-done is structured. A finance team verifies 5K-vendor GSTIN status monthly for ITC compliance. A KYB platform offers vendor-onboarding GSTIN verification as a service feature. A procurement function validates new-supplier GSTINs at onboarding (one-time lookup) + monitors active suppliers for status changes (recurring). A B2B SaaS providing India-tax software integrates GSTIN-status checks into invoice workflows. All reduce to GSTIN list + verification batch + status-change alerting.

How does this compare to the alternatives?

Three options for GSTIN verification:

Approach Cost per 1,000 GSTINs Reliability Setup time Maintenance
GSTN official API (via GSP) Commercial agreement + per-call Authoritative GSP onboarding required Provider-managed
Manual GSTN portal lookup Effectively unbounded Low (rate-limited) Continuous Doesn't scale
Thirdwatch GST Verification Scraper $1.20–$2.00/1K results Public-index snapshot + checksum validation 5 minutes Thirdwatch tracks source changes

GSTN's official integrations require an authorized route. The GST Verification Scraper actor page provides a cheaper public-index screening layer; it is not a substitute for an authoritative GSTN/GSP response when a regulated decision requires one.

How to verify GSTINs in 4 steps

Step 1: How do I authenticate against Apify?

Sign in at apify.com (free tier, no credit card), open Settings → Integrations, and copy your personal API token:

export APIFY_TOKEN="apify_api_xxxxxxxxxxxxxxxx"

Step 2: How do I bulk-verify a vendor list?

Pass GSTIN array.

import os, requests, pandas as pd

ACTOR = "thirdwatch~gst-verification-scraper"
TOKEN = os.environ["APIFY_TOKEN"]

VENDORS = [
    "27AABCT3518Q1ZS",  # Example only
    "29AABCM1234R1ZQ",
    "07AABCS5678P1ZW",
    # ... up to 1000 GSTINs per batch
]

resp = requests.post(
    f"https://api.apify.com/v2/acts/{ACTOR}/run-sync-get-dataset-items",
    params={"token": TOKEN},
    json={"queries": VENDORS, "maxResults": 1000, "concurrency": 8},
    timeout=900,
)
df = pd.DataFrame(resp.json())
print(f"{len(df)} GSTINs verified")
print(f"Indexed: {(df.verification_status == 'verified').sum()}")
print(f"Not indexed: {(df.verification_status == 'not_indexed').sum()}")
print(f"Invalid input: {df.verification_status.str.startswith('invalid_').sum()}")

The Actor accepts up to 10,000 unique inputs. A global three-request-per-second cap keeps bulk execution predictable; monthly full-list refresh plus on-demand checks for new vendors is usually sufficient.

Step 3: How do I detect status changes vs prior snapshot?

Compare daily snapshots and alert on status flips.

import pandas as pd, glob, json, requests as r

snapshots = sorted(glob.glob("snapshots/gst-*.json"))
dfs = []
for s in snapshots:
    snap = pd.DataFrame(json.loads(open(s).read()))
    snap["snapshot_date"] = pd.to_datetime(s.split("-")[-1].split(".")[0])
    dfs.append(snap)

all_df = pd.concat(dfs, ignore_index=True)
latest = all_df[all_df.snapshot_date == all_df.snapshot_date.max()]
prev = all_df[all_df.snapshot_date == sorted(all_df.snapshot_date.unique())[-2]]

merged = latest.merge(prev, on="gstin", suffixes=("", "_prev"))
status_changes = merged[merged.status != merged.status_prev]

for _, row in status_changes.iterrows():
    r.post("https://hooks.slack.com/services/.../...",
             json={"text": (f":warning: GSTIN {row.gstin} ({row.business_name}) "
                          f"changed: {row.status_prev}{row.status}")})
print(f"{len(status_changes)} status changes alerted")

Status flips such as Active → Cancelled or Suspended should enter a compliance-review queue before the record drives payment or tax decisions.

Step 4: How do I push to compliance Postgres?

Upsert per GSTIN with snapshot history.

import psycopg2

with psycopg2.connect(...) as conn, conn.cursor() as cur:
    for _, v in df.iterrows():
        cur.execute(
            """INSERT INTO gst_vendors (gstin, legal_name, trade_name, status,
                                          state_jurisdiction, taxpayer_type,
                                          last_verified)
               VALUES (%s,%s,%s,%s,%s,%s, current_date)
               ON CONFLICT (gstin) DO UPDATE SET
                 status = EXCLUDED.status,
                 last_verified = current_date""",
            (v.gstin, v.business_name, v.get("trade_name"), v.status,
             v.state_jurisdiction, v.taxpayer_type)
        )
print(f"Upserted {len(df)} GSTIN records")

Sample output

A single GSTIN verification record looks like this. Five rows weigh ~5 KB.

{
  "gstin": "27AADCB2230M1ZT",
  "business_name": "BILT GRAPHIC PAPER PRODUCTS LIMITED",
  "trade_name": null,
  "status": "Active",
  "registration_date": "June 30, 2017",
  "registration_date_iso": "2017-06-30",
  "state": "Maharashtra",
  "state_jurisdiction": "CHANDRAPUR_501",
  "taxpayer_type": "Regular",
  "constitution": "Public Limited Company",
  "valid_format": true,
  "checksum_valid": true,
  "verification_status": "verified",
  "data_source": "razorpay",
  "verified_at": "2026-07-16T16:30:00Z"
}

gstin is the canonical natural key. verification_status tells you whether detailed source data was found, while status, business_name, and trade_name support comparisons with vendor-onboarding records. Use registration_date_iso for machine comparisons; registration_date retains the source display value for backward compatibility.

Common pitfalls

Three things go wrong in GSTIN verification pipelines. GSTIN format validation — validate both the 15-character shape and checksum before a source lookup. State-jurisdiction nuance — GSTIN encodes state of registration, but a vendor may operate across states; do not substitute that code for an invoice or operating address. Status nuanceActive, Suspended, and Cancelled are distinct review signals; route non-active outcomes to an authoritative GSTN/GSP check before applying a business rule.

Thirdwatch reads a public Razorpay index over direct HTTP and returns explicit provenance. Pair GST Verification with IndiaMart Scraper for supplier discovery, but send not_indexed and high-risk decisions to the official portal or a licensed GSP rather than treating absence from a public index as a definitive compliance result.

Operational best practices for production pipelines

Tier the cadence to match signal half-life. Monthly polling on the full vendor list plus on-demand lookups for new vendors is a practical starting point; regulated workflows should set cadence from their own risk policy.

Snapshot raw payloads. Pipeline cost is dominated by scrape volume, not storage. Persisting raw JSON snapshots lets you re-derive metrics — particularly useful for retrospective compliance audits. Compress with gzip at write-time.

Schema validation. Assert the stable contract (gstin, verification_status, valid_format, checksum_valid, data_source) on every run. Measure non-null business fields only among verification_status == "verified" rows; mixing not_indexed and invalid-input outcomes into completeness metrics gives a misleading quality score. Persist field-level diffs for status and business-name changes, and route them to a human reviewer before taking a regulated action.

For cost-controlled pipelines, hash each returned record and run downstream enrichment or alerting only when the hash changes. This does not remove the source lookup, but it avoids repeating more expensive downstream work for unchanged snapshots.

Related use cases

Frequently asked questions

Why automate GSTIN verification?

Supplier-master data changes over time, and a typo in a 15-character GSTIN is difficult to spot by eye. Automated format, checksum, and public-index checks make vendor onboarding and periodic compliance review reproducible at scale.

What data does the actor return per GSTIN?

Indexed records include business_name, trade_name, status, registration_date, taxpayer_type, constitution, state and central jurisdiction, address when present, PAN, and provenance. Every input also receives format and checksum validation. The Actor does not return filings, turnover, signatories, or e-invoice status.

How does the actor handle anti-bot defenses?

The Actor reads structured JSON embedded in Razorpay's public server-rendered GST index over HTTP. It uses no browser, login, captcha solver, or user API key, caps traffic at three requests per second, and reserves a rotating datacenter request for persistent source-side blocks.

Can I bulk-verify a vendor list?

Yes. Pass up to 10,000 GSTINs in `queries`. The Actor deduplicates inputs, uses eight workers by default, and writes unbilled upstream failures to a separate ERRORS record for replay.

How fresh do GSTIN snapshots need to be?

For active vendor compliance (ongoing transactions), monthly cadence catches status changes (cancellations, suspensions). For high-stakes transactions (large invoices, contracts), per-transaction lookup at point-of-payment. For comprehensive vendor due-diligence, quarterly full-list refresh + alerts on status changes.

How does this compare to GSTN's official API?

The Actor is a low-cost public-index snapshot, not an authoritative GSTN/GSP feed. Use it for format/checksum validation, screening, and monitoring; cross-check high-risk or regulated decisions with the official portal or a licensed GSP.

Related

Try it yourself

100 free credits, no credit card.

About 30 real searches. Add the MCP to Claude or Cursor in two minutes.