Skip to main content

Async Python client for Indian court data — eCourts, HC Services, Supreme Court

Project description

bharat-courts

Async Python SDK for Indian court data — search cases, download orders, and access cause lists from eCourts and the Supreme Court.

Python 3.11+ License: MIT PyPI


What is this?

Access to court records is fundamental to legal transparency and the rule of law. India's eCourts platform holds millions of case records across 25+ High Courts and the Supreme Court — but programmatic access is difficult.

bharat-courts makes it easy. It provides a clean async Python interface to:

  • Search cases by number, party name, or advocate across any High Court
  • Download court orders and judgment PDFs
  • Get daily cause lists — see which cases are being heard today, by bench
  • Look up case types and bench info for all 25 High Courts
  • Automate CAPTCHA handling with built-in OCR

Built for legal researchers, civic tech projects, legal aid organizations, journalists, and anyone working to make Indian judicial data more accessible. All responses are returned as typed Python dataclasses with JSON serialization.

Installation

pip install bharat-courts

# With automatic CAPTCHA solving (recommended)
pip install bharat-courts[ocr]

# With CLI
pip install bharat-courts[cli]

# Everything (OCR + CLI + dev tools)
pip install bharat-courts[all]

Requires Python 3.11+

Quick Start

Search cases by party name

import asyncio
from bharat_courts import get_court, HCServicesClient
from bharat_courts.captcha.ocr import OCRCaptchaSolver

async def main():
    delhi = get_court("delhi")
    solver = OCRCaptchaSolver()

    async with HCServicesClient(captcha_solver=solver) as client:
        cases = await client.case_status_by_party(
            delhi,
            party_name="kumar",
            year="2024",
        )
        for case in cases[:5]:
            print(f"{case.cnr_number}: {case.petitioner} v {case.respondent}")
            print(f"  Status: {case.status}")

asyncio.run(main())
DLHC010582482024: VIKRAM KUMAR v CHIEF ELECTION COMMISSION & ORS.
  Status: Pending
DLHC010400092024: ARVIND KUMAR JAIN v UNION OF INDIA
  Status: Disposed
...

Search by case number

cases = await client.case_status(
    delhi,
    case_type="134",     # W.P.(C) — use list_case_types() to discover codes
    case_number="1",
    year="2024",
)

Get today's cause list

pdfs = await client.cause_list(delhi, civil=True)
for pdf in pdfs:
    print(f"{pdf.bench}")
    print(f"  PDF: {pdf.pdf_url}")
HON'BLE MR. JUSTICE V. KAMESWAR RAO, HON'BLE MS. JUSTICE MANMEET PRITAM SINGH ARORA
  PDF: https://hcservices.ecourts.gov.in/hcservices/cases_qry/cases/display_causelist_pdf.php?...
HON'BLE MR. JUSTICE PRATEEK JALAN
  PDF: https://hcservices.ecourts.gov.in/hcservices/cases_qry/cases/display_causelist_pdf.php?...

List benches and case types (no CAPTCHA needed)

benches = await client.list_benches(delhi)
# {'1': 'Principal Bench at Delhi'}

case_types = await client.list_case_types(delhi)
# {'134': 'W.P.(C)(CIVIL WRITS)-134', '27': 'W.P.(CRL)...', ...}

Court registry

from bharat_courts import get_court, list_high_courts

# Look up any court
delhi = get_court("delhi")       # Delhi High Court (state_code="26")
bombay = get_court("bombay")     # Bombay High Court (state_code="1")
sci = get_court("sci")           # Supreme Court of India

# List all High Courts
for court in list_high_courts():
    print(f"{court.code}: {court.name} (state_code={court.state_code})")

JSON serialization

All models support to_dict() and to_json():

case = cases[0]
print(case.to_json(indent=2))
{
  "case_number": "3/2024",
  "case_type": "3",
  "cnr_number": "DLHC010582482024",
  "petitioner": "VIKRAM KUMAR",
  "respondent": "CHIEF ELECTION COMMISSION & ORS.",
  "status": "Pending",
  "court_name": "Delhi High Court"
}

Supported Portals

Portal Client Status
HC Services HCServicesClient Fully working
Judgment Search JudgmentSearchClient Basic search
Supreme Court SCIClient Basic search

HC Services — Full API

Method CAPTCHA Description
list_benches() No Available benches for a High Court
list_case_types() No Case type codes (W.P.(C) = 134, etc.)
case_status() Yes Search by case number
case_status_by_party() Yes Search by party name + year
court_orders() Yes Get orders for a case
cause_list() Yes Today's cause list PDFs by bench
download_order_pdf() No Download order/judgment PDF

CAPTCHA Handling

HC Services uses Securimage CAPTCHAs that are pinned to the PHP session. The built-in OCR solver (ddddocr) has ~60% accuracy — failed attempts are automatically retried with fresh sessions (up to 3 attempts by default).

from bharat_courts.captcha.ocr import OCRCaptchaSolver

# Automatic OCR (requires pip install bharat-courts[ocr])
solver = OCRCaptchaSolver()

For higher accuracy, implement a custom solver:

from bharat_courts.captcha.base import CaptchaSolver

class MyCaptchaSolver(CaptchaSolver):
    async def solve(self, image_bytes: bytes) -> str:
        # Send to a CAPTCHA service, ML model, etc.
        return "solved_text"

async with HCServicesClient(captcha_solver=MyCaptchaSolver()) as client:
    ...

Or use the manual solver for interactive use:

from bharat_courts.captcha.manual import ManualCaptchaSolver

# Opens the CAPTCHA image and prompts on stdin
solver = ManualCaptchaSolver()

CLI

# List all courts
bharat-courts courts
bharat-courts courts --type hc   # High Courts only

# Search case status (requires CAPTCHA — uses ManualCaptchaSolver by default)
bharat-courts search delhi --case-type 134 --case-number 1 --year 2024

# Get cause list
bharat-courts cause-list delhi
bharat-courts cause-list delhi --date 01-03-2026

# Get court orders
bharat-courts orders delhi --case-type 134 --case-number 1 --year 2024

# Search judgments
bharat-courts judgments delhi --from-date 01-01-2024 --to-date 31-01-2024

# Supreme Court
bharat-courts sci --year 2024 --month 6

# Install AI agent skills (Claude Code, Copilot, etc.)
bharat-courts install-skills

Configuration

Environment variables with BHARAT_COURTS_ prefix:

Variable Default Description
BHARAT_COURTS_REQUEST_DELAY 1.0 Seconds between requests
BHARAT_COURTS_TIMEOUT 30 Request timeout (seconds)
BHARAT_COURTS_MAX_RETRIES 3 Retry count on failure
BHARAT_COURTS_LOG_LEVEL INFO Logging level

Or use a .env file. See .env.example.

Supported Courts

All 25 High Courts with verified eCourts state codes:

Court Code State Code
Allahabad HC allahabad 13
Andhra Pradesh HC andhra 2
Bombay HC bombay 1
Calcutta HC calcutta 16
Chhattisgarh HC chhattisgarh 18
Delhi HC delhi 26
Gauhati HC gauhati 6
Gujarat HC gujarat 17
Himachal Pradesh HC himachal 5
J&K HC jammu 12
Jharkhand HC jharkhand 7
Karnataka HC karnataka 3
Kerala HC kerala 4
Madhya Pradesh HC mp 23
Madras HC madras 10
Manipur HC manipur 25
Meghalaya HC meghalaya 21
Orissa HC orissa 11
Patna HC patna 8
Punjab & Haryana HC punjab 22
Rajasthan HC rajasthan 9
Sikkim HC sikkim 24
Telangana HC telangana 29
Tripura HC tripura 20
Uttarakhand HC uttarakhand 15
Supreme Court sci 0

Bombay and Allahabad HCs also have bench-specific entries (e.g., bombay-nagpur, allahabad-lucknow).

Contributing

Contributions are welcome! Here's how to get set up.

Prerequisites

  • Python 3.11+ — check with python3 --version
  • git

Dev environment setup

# 1. Fork and clone
git clone https://github.com/<your-username>/bharat-courts.git
cd bharat-courts

# 2. Create a virtual environment
python3 -m venv .venv
source .venv/bin/activate   # Linux/macOS
# .venv\Scripts\activate    # Windows

# 3. Install with all extras (OCR, CLI, dev tools)
pip install -e ".[all]"

# 4. Verify everything works
pytest                                    # 43 unit tests, no network needed
ruff check . && ruff format --check .     # lint + format check

Running tests

# Unit tests (fast, offline)
pytest

# Single test file
pytest tests/test_hcservices_parser.py

# Single test
pytest tests/test_hcservices_parser.py::test_parse_case_status_json

# With verbose output
pytest -v

# Live integration tests against real eCourts portals (requires ddddocr + network)
python examples/live_test_all.py

Code style

The project uses ruff for linting and formatting:

# Check for issues
ruff check .

# Auto-fix what's possible
ruff check --fix .

# Format code
ruff format .

Config is in pyproject.toml — Python 3.11 target, 100-char line length, rules: E/F/I/N/W.

Project structure

src/bharat_courts/
├── __init__.py          # Public API exports
├── models.py            # Dataclasses: CaseInfo, CaseOrder, CauseListPDF, etc.
├── config.py            # Pydantic Settings (BHARAT_COURTS_ env prefix)
├── http.py              # Rate-limited async HTTP client (httpx)
├── courts.py            # Registry of 25+ HCs with eCourts codes
├── captcha/
│   ├── base.py          # CaptchaSolver ABC
│   ├── manual.py        # Stdin/callback solver
│   └── ocr.py           # ddddocr-based solver
├── hcservices/          # HC Services portal (primary, fully working)
│   ├── client.py        # HCServicesClient
│   ├── endpoints.py     # URL + form builders
│   └── parser.py        # JSON + HTML response parsers
├── judgments/            # Judgment Search portal (basic)
│   ├── client.py
│   ├── endpoints.py
│   └── parser.py
├── sci/                 # Supreme Court (basic)
│   ├── client.py
│   └── parser.py
└── cli.py               # Click CLI entry point

Areas where help is needed

  • Better CAPTCHA solving — the ddddocr OCR is ~60% accurate; a fine-tuned model or alternative approach would help
  • District court support — eCourts has district court portals with a different API
  • Judgment Search portal — the JudgmentSearchClient needs more thorough testing and pagination support
  • Supreme Court clientSCIClient is basic; the SCI website structure changes frequently
  • More High Court coverage — test the client against courts beyond Delhi/Bombay/Allahabad
  • Documentation — API docs, more examples, tutorials

Submitting changes

  1. Fork the repo and create a branch (git checkout -b my-feature)
  2. Make your changes
  3. Run pytest and ruff check . to ensure tests pass and code is clean
  4. Commit with a descriptive message
  5. Open a pull request

How it works

The eCourts HC Services portal (hcservices.ecourts.gov.in) uses a PHP backend with:

  1. Session cookiesGET main.php establishes HCSERVICES_SESSID
  2. Securimage CAPTCHAs — pinned to the session (same image within one session)
  3. AJAX POST requestscases_qry/index_qry.php with action_code parameter
  4. JSON responses{"con": ["[{...}]"], "totRecords": N, "Error": ""}

This library handles all of this transparently — session management, CAPTCHA solving with retry, request/response parsing, and rate limiting.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bharat_courts-0.1.0.tar.gz (37.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bharat_courts-0.1.0-py3-none-any.whl (36.8 kB view details)

Uploaded Python 3

File details

Details for the file bharat_courts-0.1.0.tar.gz.

File metadata

  • Download URL: bharat_courts-0.1.0.tar.gz
  • Upload date:
  • Size: 37.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bharat_courts-0.1.0.tar.gz
Algorithm Hash digest
SHA256 bc9ee8e1a36684f40a0ed8af18b59db8c11debb0eb38ea1fb42d5c78d657f4c4
MD5 ae9ba65f6605f70f7acd1b05634d6ecc
BLAKE2b-256 840745f9c187e8aab0c9ffe0d3e7f764a32504a45e8cf3a51bba8c96422cde3c

See more details on using hashes here.

Provenance

The following attestation bundles were made for bharat_courts-0.1.0.tar.gz:

Publisher: python-publish.yml on iamshouvikmitra/bharat-courts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bharat_courts-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: bharat_courts-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 36.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bharat_courts-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 eb8929dbc5cdda2dfe6ac1c0a52246d8f7004eac3a954cfe423e5e4aac1fd78c
MD5 a810306905f52678b9da5367f2443ea0
BLAKE2b-256 4c7341713ca4a22dfe4a9929cab921ffa007f1baae22f99ed65ab5c34d138942

See more details on using hashes here.

Provenance

The following attestation bundles were made for bharat_courts-0.1.0-py3-none-any.whl:

Publisher: python-publish.yml on iamshouvikmitra/bharat-courts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page