PRODUCTION AUTOMATION SUITE · IO2I OUTSOURCING
LWT Diary: Legal Workflow Automation Suite
A unified suite of tribunal and court automation pipelines engineered for legal operations at IO2i Outsourcing Pvt. Ltd. Consolidates four domain-specific automation modules—DRT/DRAT, NCLT, e-Jagriti, and High Courts e-Courts Services—turning hours of daily manual docket searches, CAPTCHA challenges, cause-list checks, and order PDF downloads into reliable, unattended execution pipelines.
ORGANIZATION & REPOIO2i Outsourcinglwt_drt_diary Core
SUITE ARCHITECTURE4 Specialized ModulesIsolated Domain State
SHARED RUNTIME TOOLSPython 3.12 · PlaywrightTesseract + PyMuPDF
TOTAL TRIBUNAL REACH60+ Benches NationwideDRT, NCLT, NCDRC, HCs
01. SUITE CONTEXT & OPERATIONAL PROBLEM
The Reality of Fragmented Judicial Tribunals in India
Legal and financial operations at IO2i manage institutional recovery disputes, corporate debt restructuring, consumer arbitrations, and High Court appeals on behalf of major banks and financial entities. Litigation teams are required to continuously monitor hundreds of active proceedings across four separate judicial systems.
However, there is no single unified judicial API in India. Each court portal operates on legacy government software stacks with fundamentally incompatible architectures:
- Debt Recovery Tribunals (DRT/DRAT): Renders challenge digits onto dynamic HTML5 canvas elements via JavaScript and traps case history within asynchronous Bootstrap modal fade cycles.
- National Company Law Tribunal (NCLT): Spans 15 regional zonal benches and 21 insolvency case categories under the IBC, burying crucial order links inside nested DOM collapse accordions.
- Consumer Commissions (e-Jagriti): Distributes hearings across National (NCDRC), State (SCDRC), and District (DCDRC) commissions, requiring high-frequency morning cause-list updates while guarding case statuses behind alphanumeric CAPTCHAs.
- High Courts e-Courts Services: Enforces a nationwide 16-character Case Number Record (CNR) lookup guarded by heavily distorted Securimage CAPTCHAs and strict session timeouts.
// ARCHITECTURAL STRATEGY: SPECIALIZED DOMAIN MODULESRather than attempting a fragile, one-size-fits-all generic crawler, LWT Diary was designed as a cohesive suite of four specialized, independently operable modules inside repository lwt_drt_diary. Each module shares core utilities for browser orchestration, OCR cleaning, and PDF parsing, but encapsulates portal-specific navigation, CAPTCHA solvers, and error recovery logic.
02. MODULE SPECIFICATIONS & ARCHITECTURE
Cross-Module Architecture & Implementation Matrix
Each module addresses distinct technical constraints across ingress, CAPTCHA resolution, DOM extraction, and document generation:
| MODULE | PORTAL & BENCHES | INGRESS & RUNTIME | CAPTCHA RESOLUTION | OUTPUT & SPECIAL FEATURES |
|---|
| 01. DRT / DRAT | drt.gov.in (44 Tribunals) | Playwright + Chrome CDP | HTML5 Canvas toDataURL() + Tesseract PSM 10 | Webex VC notice extraction, Roznama text quality scoring, SHA-256 PDF caching |
| 02. NCLT | nclt.gov.in (15 Zonal Benches) | Playwright + ThreadPoolExecutor | Direct image OCR | Accordion DOM unfolding, unclipped CDP PDF dossiers, 5-worker concurrent order download |
| 03. e-Jagriti | e-jagriti.gov.in (National/State/District) | Dual-Path: REST API + Playwright | In-memory PIL greyscale + Punctuation blacklist | Zero-browser REST cause lists, wire-level JSON response interception on /getCaseStatus |
| 04. High Courts | hcservices.ecourts.gov.in | Playwright + Python 3.12 | 5-Variant PIL filtering + Consensus majority voting | 16-char CNR dual regex validation, pointer-events CSS unblocking, isolated A4 PDF printing |
MODULE 01 · DEBT RECOVERY TRIBUNAL & APPELLATE TRIBUNAL
DRT & DRAT Case Tracker & Cause-List Pipeline
e_drt44 TribunalsHTML5 Canvas OCR
Debt Recovery Tribunals adjudicate specialized financial recovery claims under the RDDBFI Act and SARFAESI Act. The module supports 4 distinct search modes: Diary Number, Case Number, Party Name, and Advocate Name across 39 DRTs and 5 DRATs nationwide.
Authentic Module Execution: Automated Playwright session driving Chromium, resolving canvas CAPTCHAs, and extracting case proceedings from drt.gov.in.
Technical Implementation & Key Challenges:
- HTML5 Canvas CAPTCHA Extraction: The portal draws challenge numbers dynamically onto a canvas element with no static image source. The solver executes in-browser JavaScript to inspect
toDataURL(). To handle asynchronous redraws, the function snapshots the previous canvas data URL and waits until a genuinely different canvas payload (> 1,000 bytes) renders before triggering screenshot capture and Tesseract OCR with PSM 10 numeric whitelist. - Bootstrap Modal State Synchronization: Search results render in asynchronous Bootstrap modal overlays. The pipeline awaits modal DOM visibility, extracts case summaries, parties, and listings, and captures courtroom Webex video conference meeting numbers and passwords embedded in cause-list rows.
- Heuristic Text Quality Scoring & Roznama Corrections: Scanned court orders (*roznama* proceedings) uploaded by clerks frequently produce noisy OCR text. The pipeline calculates a heuristic score based on alphanumeric ratio, word length, and judicial keyword presence (*roznama, registrar, advocate, drt, adjourn*). Low-scoring documents undergo dictionary-based typo corrections.
Sanitized Source Excerpt: e_drt/case_details_service/main.py
TESSERACT_CONFIG = "--psm 10 --oem 3 -c tessedit_char_whitelist=0123456789"
def solve_captcha(page: Page) -> tuple[str, str]:
page.wait_for_selector("canvas[data-testid='captcha-canvas']", timeout=DEFAULT_TIMEOUT)
# Wait until canvas is actually drawn (data URL length > 1000 bytes)
page.wait_for_function(
"() => { const c = document.querySelector('canvas[data-testid="captcha-canvas"]'); return c && c.toDataURL().length > 1000; }",
timeout=DEFAULT_TIMEOUT
)
img_bytes = page.locator("canvas[data-testid='captcha-canvas']").screenshot()
img = Image.open(io.BytesIO(img_bytes)).convert('L')
raw_text = pytesseract.image_to_string(img, config=TESSERACT_CONFIG).strip()
cleaned_text = ''.join(filter(str.isdigit, raw_text))
return raw_text, cleaned_textMODULE 02 · NATIONAL COMPANY LAW TRIBUNAL
NCLT Insolvency Case Tracking & Order Dossier Engine
nclt_service15 Zonal BenchesPyMuPDF + OCR
The National Company Law Tribunal adjudicates corporate insolvency resolution processes (CIRP) and liquidation matters under the Insolvency and Bankruptcy Code (IBC). This module monitors case dockets across 15 zonal locations (including Principal Bench New Delhi, Mumbai, Kolkata, Chennai, and Bengaluru).
Authentic Module Execution: Querying insolvency case status, parsing hearing dates, and downloading newly uploaded court order PDFs.
Technical Implementation & Key Challenges:
- DOM Accordion Unfolding for Archival: NCLT case histories store party details, filings, and orders inside nested Bootstrap accordion elements. Standard screenshots clip hidden elements. The module evaluates JavaScript injecting the
show class across all .collapse selectors, then triggers Chrome DevTools Protocol (Page.printToPDF) to produce a comprehensive, unclipped A4 case dossier. - Bounded Multi-Threaded Order Downloads: Corporate insolvency dockets frequently contain dozens of historic daily hearing orders. To eliminate browser overhead while protecting court servers from socket exhaustion, order URLs are downloaded via Python's
ThreadPoolExecutor bounded to 5 concurrent worker threads. - Dual-Layer Text Extraction (PyMuPDF + Tesseract): Downloaded orders are evaluated page-by-page with PyMuPDF (
fitz). If selectable text density falls below a quality threshold (< 0.35) and raster image layers exist, the pipeline automatically falls back to page-level Tesseract OCR.
Sanitized Source Excerpt: nclt_service/case_history/main.py
def print_page_to_pdf(page: Page, pdf_path: str) -> bool:
try:
# Expand all accordion/collapse elements so all sections are visible
page.evaluate("""() => {
document.querySelectorAll(".collapse").forEach(el => {
el.classList.add("show");
el.style.display = "block";
});
}""")
# Print via Chrome CDP session (works in both headed and headless modes)
cdp = page.context.new_cdp_session(page)
res = cdp.send("Page.printToPDF", {
"printBackground": True,
"preferCSSPageSize": True
})
pdf_bytes = base64.b64decode(res["data"])
with open(pdf_path, "wb") as f:
f.write(pdf_bytes)
return True
except Exception as e:
print(f"Failed to print page to PDF: {e}")
return FalseMODULE 03 · NATIONAL CONSUMER DISPUTE REDRESSAL COMMISSION
e-Jagriti Consumer Commission Scraper & API Pipeline
e_jagritiDual-Path ArchitectureWire Interception
The e-Jagriti platform governs consumer dispute resolution across National (NCDRC), State (SCDRC), and District (DCDRC) commissions. The module was architected with a decoupled dual-path design to separate high-frequency morning cause-list checks from CAPTCHA-gated case status inquiries.
Authentic Module Execution: Automated case number search and status verification on the e-Jagriti consumer dispute portal.
Technical Implementation & Key Challenges:
- Direct REST API Ingestion for Cause Lists: Morning daily cause lists are published without requiring CAPTCHA verification. Instead of spawning heavy browser sessions, the cause-list pipeline calls the portal's upstream REST endpoints directly via Python
requests, reducing execution latency from ~20 seconds to sub-second responses. - Wire-Level JSON Response Interception: For case status queries, the portal is an Angular single-page application. Rather than parsing fragile, dynamically mutating HTML DOM tables, the Playwright automation registers an asynchronous network event listener (
page.on("response", ...)). When the frontend calls /getCaseStatus, the handler intercepts and captures the raw JSON payload directly from the HTTP wire. - In-Memory Alphanumeric CAPTCHA OCR: Alphanumeric CAPTCHAs are captured into memory as raw PIL byte streams without writing temporary image files to disk, solved via Tesseract PSM 8 with a targeted punctuation blacklist to prevent character-symbol confusion.
Sanitized Source Excerpt: e_jagriti/complete-case-details/main.py
case_status_data = {}
# Intercept initial case data load directly from backend API
def intercept_case_status(response):
nonlocal case_status_data
try:
if "getCaseStatus" in response.url and response.status == 200:
data = response.json()
if data and data.get("status") == 200:
case_status_data = data.get("data", {})
except Exception:
pass
page.on("response", intercept_case_status)
submit_meta = submit_form(page)MODULE 04 · HIGH COURTS eCOURTS SERVICES
High Courts Services & CNR Pipeline
High_Courts16-Char CNR5-Variant OCR Voting
The High Court Services portal (hcservices.ecourts.gov.in) provides judicial dockets across Indian High Courts. This module implements single-lookup and batch processing via the nationwide 16-character Case Number Record (CNR) code.
Authentic Module Execution: Resolving High Court CNR inquiries, solving Securimage CAPTCHAs, and extracting case details.
Technical Implementation & Key Challenges:
- Strict 16-Character CNR Validation: Before initiating browser sessions, the module validates the input string against dual regex rules (
HCxxNN... and xxHCNN...), rejecting malformed inputs before incurring network overhead. - 5-Variant Image Transformation & Majority-Vote OCR: High Court Securimage CAPTCHAs feature heavy background noise, shearing, and distorted letterforms. The solver generates 5 PIL image transformations (autocontrast, 4x scaling, contrast/sharpness boost, binary thresholding, and median filtering) and runs Tesseract across PSM 8, 7, and 13. When multiple candidate strings emerge, a
collections.Counter consensus algorithm selects the majority-vote result. - CSS Pointer-Events Override: The portal frequently overlays a transparent container (
#captcha_container_2) that intercepts click events and blocks form submission. The automation programmatically overrides CSS pointer-events via JavaScript injection to guarantee reliable form submission. - Clean A4 PDF Dossiers: Rather than printing chaotic full-page web layouts, the module creates an isolated DOM container containing only structured case headers, party details, and order history, printing a standardized legal A4 PDF dossier.
Sanitized Source Excerpt: High_Courts/cnr_service/main.py
def ocr_captcha(png: bytes) -> str:
gray = ImageOps.autocontrast(Image.open(io.BytesIO(png)).convert("L"))
w, h = gray.size
big = gray.resize((max(w * 4, 400), max(h * 4, 140)))
variants = [
big,
ImageEnhance.Contrast(ImageEnhance.Sharpness(big).enhance(2.0)).enhance(1.8),
big.point(lambda x: 0 if x < 150 else 255),
ImageOps.invert(big),
big.filter(ImageFilter.MedianFilter(3)).point(lambda x: 0 if x < 155 else 255),
]
hits: List[str] = []
for img in variants:
for psm in (8, 7, 13):
raw = pytesseract.image_to_string(img, config=f"--psm {psm} -c tessedit_char_whitelist={WHITELIST}") or ""
cleaned = re.sub(r"[^0-9a-zA-Z]", "", raw)
if len(cleaned) == 6:
return cleaned
if cleaned:
hits.append(cleaned)
six = [c for c in hits if len(c) == 6]
return Counter(six).most_common(1)[0][0] if six else ""07. IMPLEMENTATION STATUS & BOUNDARIES
Implementation Status & Honest Technical Boundaries
IMPLEMENTATION STATUS MATRIX- Verified & Implemented: All four automation pipelines are implemented in Python within the
lwt_drt_diary project tree. Verified by raw screen recordings against live portal backends: DRT/DRAT canvas extraction, NCLT accordion unfolding and multi-threaded order fetching, e-Jagriti REST cause lists and wire interception, and High Courts 16-character CNR processing with consensus OCR voting. - Architectural Boundary: While the modules reside within the unified
lwt_drt_diary suite built for IO2i, they operate as distinct, specialized automation services rather than a single monolithic web app. Each module maintains its own browser session configurations, selectors, and CAPTCHA algorithms tailored to its respective court portal. - External Portal Countermeasures: Government court portals frequently impose rate-limits, IP bans on aggressive scraping, and unannounced DOM class renames. The pipelines incorporate exponential retry loops, session recycling, and fallback heuristics, but require periodic selector maintenance when government portals undergo major redesigns.
08. LESSONS LEARNED & TAKEAWAYS
Core Engineering Takeaways from Building Judicial Automation
Engineering automation for real-world legal portals reinforced critical design principles:
- Intercepting the Wire Beats Scraping the DOM: Where portals use single-page applications (like e-Jagriti), capturing backend JSON API responses via network interception (
page.on("response")) is vastly more robust than parsing constantly changing HTML tables and CSS selectors. - Image Preprocessing Dominates Raw OCR Models: Tesseract fails on distorted CAPTCHAs without preprocessing. Applying contrast boosting, sharp thresholding, and consensus voting across multiple transformations produced dramatic accuracy gains without needing heavy deep-learning infrastructure.
- Heuristic Text Scoring Avoids Wasteful OCR: Parsing order PDFs with PyMuPDF first and only invoking page-level OCR when selectable text density is low saved massive compute overhead across thousands of archived court orders.