I’m trying to batch-download PDF judgments from https://judgments.ecourts.gov.in using plain requests, but their built-in math CAPTCHA keeps breaking my pipeline. I’ve rolled my own solution with easyocr to read the math challenge and a small parser to compute the result, but I still see: OCR mis-reads (e.g. confusing “×” vs “x”) Timeouts after solving multiple CAPTCHAs in quick succession Session-expiration errors that require me to reset the entire Session What my CAPTCHA-solver code looks like Below is the core function I use to fetch the CAPTCHA image, OCR it with EasyOCR, then evaluate the simple math expression. It often mis-extracts characters or returns malformed strings: import re import requests import easyocr ROOT = "https://judgments.ecourts.gov.in" CAPTCHA_URL = ROOT + "/pdfsearch/vendor/securimage/securimage_show.php" # Initialize the OCR reader only once reader = easyocr.Reader(["en"], gpu=False) def solve_captcha(session: requests.Session) -> str: """ 1. Download the CAPTCHA image. 2. Pass raw bytes into easyocr for text extraction. 3. Parse the returned string as a simple arithmetic expression. 4. Return the computed result as a string. """ # Step 1: fetch image res = session.get(CAPTCHA_URL, verify=False, timeout=30) img_bytes = res.content # Step 2: OCR the contents ocr = reader.readtext(img_bytes) if not ocr: raise RuntimeError("OCR returned no text") expr = ocr[0][1].strip() # e.g. "12 × 3" # Step 3: parse "number operator number" m = re.match(r"(\d+)\s*([+\-×Xx÷/])\s*(\d+)", expr) if not m: raise RuntimeError(f"Unexpected format from OCR: {expr}") a_str, op, b_str = m.groups() a, b = int(a_str), int(b_str) # Step 4: evaluate if op == "+": return str(a + b) if op == "-": return str(a - b) if op in ("×","X","x","*"): return str(a * b) if op in ("÷","/"): return str(a // b) raise RuntimeError(f"Unknown operator: {op}") How I integrate it into my scraper Right after solving the CAPTCHA, I post the answer to their token endpoint: # after solve_captcha(session) returns a string `captcha_ans`: token_resp = session.post( CAPTCHA_TOKEN_URL, headers={"X-Requested-With": "XMLHttpRequest", "Content-Type": "application/x-www-form-urlencoded"}, data={"captcha": captcha_ans, "ajax_req": "true"}, verify=False, timeout=30 ) If the token is accepted I proceed to request the PDF link; otherwise I get an error and retry. The error I’m seeing Even when the OCR reads something that looks valid, I sometimes get back: 400 Bad Request: errormsg=“Invalid CAPTCHA” Or the session silently expires and I’m forced to call: session = requests.Session() What I’ve already tried Resetting the Session every 25 downloads Basic image preprocessing (grayscale → thresholding → dilation) before OCR Fallback to Selenium + Tesseract (still unreliable) Tuning EasyOCR parameters (GPU vs CPU, different model sizes) What I’m looking for Open-source projects or Python libraries with a more reliable CAPTCHA-bypass for ecourts.gov.in (or similar math/image CAPTCHAs). Architectural patterns for a high-throughput scraper that gracefully handles CAPTCHA failures and session resets. Recommendations for paid/hosted CAPTCHA-solving services or APIs that have a smooth requests-based integration (if no better open-source option exists). Any pointers to existing GitHub repos, code samples, or best practices would be hugely appreciated—thanks! Continue reading...