# eCourts Case Scraper (`codingfrontend/ecourts-case-scraper`) Actor

A robust, high-performance utility designed for developer automation, data integration, and AI training. Features built-in captcha bypass, headful/headless browser execution, and proxy support to scrape eCourts data seamlessly, reliably, and at scale.

- **URL**: https://apify.com/codingfrontend/ecourts-case-scraper.md
- **Developed by:** [Coding Frontned](https://apify.com/codingfrontend) (community)
- **Categories:** Automation, Developer tools, AI
- **Stats:** 63 total users, 3 monthly users, 29.0% runs succeeded, 3 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $3.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What this Actor does

This Actor looks up Indian court cases on the official [eCourts Services website](https://services.ecourts.gov.in/ecourtindia_v6/) using each case's 16-character CNR. It returns structured case details when eCourts provides a verifiable case record.

Use it to review case status, registration details, parties and advocates, acts, FIR details, hearing history, and order metadata. The Actor follows eCourts' browser lookup form and requires a CAPTCHA solver key configured as a protected Actor secret.

### Start a run

1. In the Actor settings, add `CAPTCHA_API_KEY` as a protected secret or environment variable. Do not put the key in Actor input.
2. Open the **Input** tab and enter one or more CNRs. Each value has four letters followed by twelve digits.
3. Adjust retry or proxy settings if needed. Apify residential Proxy is enabled by default.
4. Click **Start**. When the run finishes, open **Case Records** for saved cases and **Output summary** for the run status.

### Input

`caseNos` is required. All other input fields are optional. The Actor accepts only the fields listed here.

#### CNR lookup

| Field     | Type             | Required? | Default | What it does                                                                                                                           |
| --------- | ---------------- | --------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `caseNos` | Array of strings | Required  | None    | CNRs to look up. Each item must match four letters followed by twelve digits. Enter 1 to 100 values. Repeated CNRs are looked up once. |

Simple one-case input:

```json
{
    "caseNos": ["KARC010037582023"]
}
```

#### Retry and proxy settings

| Field                   | Type             | Required? | Default                                                        | Bounds or choices                                                              | What it does                                                                                    |
| ----------------------- | ---------------- | --------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------- |
| `maxCaptchaRetries`     | Integer          | Optional  | `3`                                                            | 1–5                                                                            | CAPTCHA solver attempts in each browser session.                                                |
| `maxSessionAttempts`    | Integer          | Optional  | `30`                                                           | 1–30                                                                           | Fresh browser and proxy sessions attempted for each unique CNR.                                 |
| `proxyCountryFallbacks` | Array of strings | Optional  | `["GB", "US", "IN"]`                                           | 1–5 unique codes; two letters, optionally followed by `_` and two more letters | Countries tried in order when Apify Proxy is used. The list cycles if more sessions are needed. |
| `proxyConfiguration`    | Object           | Optional  | `{"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}` | Only the nested fields below are accepted                                      | Selects Apify Proxy or custom proxy URLs.                                                       |

An example with fewer retries and a custom country order:

```json
{
    "caseNos": ["KARC010037582023", "KABC010006152020"],
    "maxCaptchaRetries": 2,
    "maxSessionAttempts": 8,
    "proxyCountryFallbacks": ["IN", "GB"]
}
```

#### `proxyConfiguration` fields

| Field                                 | Type             | Required? | Default           | Bounds or choices   | What it does                                                                                                                            |
| ------------------------------------- | ---------------- | --------- | ----------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `proxyConfiguration.useApifyProxy`    | Boolean          | Optional  | `true`            | `true` or `false`   | Uses Apify Proxy when custom proxy URLs are not supplied. Turning it off without custom URLs uses a direct connection.                  |
| `proxyConfiguration.apifyProxyGroups` | Array of strings | Optional  | `["RESIDENTIAL"]` | No item-count bound | Proxy groups used when Apify Proxy is enabled.                                                                                          |
| `proxyConfiguration.proxyUrls`        | Array of strings | Optional  | None              | No item-count bound | Custom proxy URLs. Country rotation is not applied to custom URLs. Keep any credentials in private settings, not shared input examples. |

For example, this disables Apify Proxy and uses a direct connection:

```json
{
    "caseNos": ["KARC010037582023"],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
}
```

The Actor removes repeated CNRs after normalizing their letter case. A successful case lookup can take multiple CAPTCHA attempts and fresh sessions, so larger batches or retry limits can take longer and use more proxy and solver traffic.

### Case records

The dataset contains verified case details only. An unsuccessful lookup, an invalid input, or an unparseable response does not create a diagnostic row. A CNR for which eCourts reports no case also has no dataset row. The run log contains failure details.

The example below is illustrative documentation data, not a verified live result. Optional fields can be absent when eCourts does not return them.

Details come from the returned case page. Order fields contain the displayed order metadata; the Actor does not download or extract PDF contents. Empty values are omitted. An act entry needs an act name, a hearing-history entry needs a judge, and an order entry needs an order number; incomplete entries are omitted while the valid case details are kept.

Hearing history contains the dates and purposes shown in the case table. The Actor does not open the separate hearing-business pages or resolve PDF document links, so it does not return the detailed proceedings text or order document URLs from those views.

```json
{
    "case_no": "KARC010037582023",
    "cnr": "KARC010037582023",
    "courtName": "District and Sessions Court, Bengaluru",
    "basicDetails": {
        "caseType": "CIVIL SUIT",
        "filingNumber": "1234/2023",
        "filingDate": "15-01-2023",
        "cnrNumber": "KARC010037582023"
    },
    "caseStatus": {
        "firstHearingDate": "20-01-2023",
        "nextHearingDate": "10-10-2024",
        "stageOfCase": "Evidence",
        "courtNumberAndJudge": "Court Room 3, Principal Judge"
    },
    "petitionerAdvocate": ["Ramesh Kumar", "Advocate - S. Sharma"],
    "respondentAdvocate": ["State of Karnataka"],
    "acts": [
        {
            "act": "Code of Civil Procedure",
            "section": "Order VII Rule 1"
        }
    ],
    "firDetails": {
        "policeStation": "Central Police Station",
        "firNumber": "56/2022"
    },
    "caseHistory": [
        {
            "judge": "Principal Judge",
            "businessOnDate": "10-01-2023",
            "hearingDate": "20-01-2023",
            "purpose": "Hearing"
        }
    ],
    "interimOrders": [
        {
            "orderNumber": "1",
            "orderDate": "20-01-2023",
            "orderType": "Notice issued"
        }
    ],
    "finalOrders": [
        {
            "orderNumber": "2",
            "orderDate": "10-10-2024",
            "orderType": "Final order"
        }
    ]
}
```

| Field                | Type              | Required? | Meaning                                                                                            |
| -------------------- | ----------------- | --------- | -------------------------------------------------------------------------------------------------- |
| `case_no`            | String            | Required  | Normalized CNR, retained as a case-number alias.                                                   |
| `cnr`                | String            | Required  | CNR used for the lookup.                                                                           |
| `courtName`          | String            | Optional  | Court heading from the case page.                                                                  |
| `basicDetails`       | Object of strings | Optional  | Registration details such as case type, filing number, and dates. Keys depend on the eCourts page. |
| `caseStatus`         | Object of strings | Optional  | Current status and hearing details. Keys depend on the eCourts page.                               |
| `petitionerAdvocate` | Array of strings  | Optional  | Petitioner and advocate entries.                                                                   |
| `respondentAdvocate` | Array of strings  | Optional  | Respondent and advocate entries.                                                                   |
| `acts`               | Array of objects  | Optional  | Acts and sections. Each object has `act` and may include `section`.                                |
| `firDetails`         | Object of strings | Optional  | FIR information, when present. Keys depend on the eCourts page.                                    |
| `caseHistory`        | Array of objects  | Optional  | Hearing history with `judge` and optional `businessOnDate`, `hearingDate`, and `purpose`.          |
| `interimOrders`      | Array of objects  | Optional  | Interim orders with `orderNumber` and optional `orderDate` and `orderType`.                        |
| `finalOrders`        | Array of objects  | Optional  | Final orders with `orderNumber` and optional `orderDate` and `orderType`.                          |

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

### Run status and output summary

The Actor counts only verified case records whose dataset writes completed. A run is `SUCCEEDED` when at least one case record was saved. If a later lookup or dataset write fails after cases were saved, the run can still succeed with `isPartial: true`. If no real case records were saved, the run is `FAILED`; diagnostic-only output never counts as a result.

The **Output summary** link opens the `OUTPUT_SUMMARY` record from the run's default **Key-value store**. It contains exactly these fields:

| Field         | Type                | Required? | Meaning                                                                                                 |
| ------------- | ------------------- | --------- | ------------------------------------------------------------------------------------------------------- |
| `status`      | String              | Required  | `SUCCEEDED` when at least one case record was saved; otherwise `FAILED`.                                |
| `itemsStored` | Nonnegative integer | Required  | Number of verified case records whose dataset writes completed.                                         |
| `isPartial`   | Boolean             | Required  | `true` when collection was interrupted or a lookup or write failed after at least one record was saved. |

Completed run:

```json
{
    "status": "SUCCEEDED",
    "itemsStored": 2,
    "isPartial": false
}
```

Run with limited results:

```json
{
    "status": "SUCCEEDED",
    "itemsStored": 1,
    "isPartial": true
}
```

Run with no saved case records:

```json
{
    "status": "FAILED",
    "itemsStored": 0,
    "isPartial": false
}
```

### Access, cost, and support

eCourts may reject automated requests, require CAPTCHA retries, rate-limit traffic, or return incomplete case pages. A failure to access or verify a case is reported in the run log, not as a dataset record. Use the service only in line with eCourts terms and applicable privacy laws.

Runs can use Apify browser compute, Apify Proxy traffic, and the separately configured CAPTCHA solver. Residential proxy use and CAPTCHA solver requests may incur charges under your accounts; prices depend on your plans and usage.

For help, use the Actor's **Issues** tab and include sanitized run-log details. Never include proxy credentials, CAPTCHA keys, or CAPTCHA values.

### W3Crawler CAPTCHA configuration

Search uses `https://api.w3crawler.com/api/captcha/solve` with model `bc3f0628-29ba-4555-9c27-ff26b4fdc179` (ECourts India Captcha). The dedicated key owned by `admin@w3crawler.com` is provided through the encrypted `CAPTCHA_API_KEY` Actor environment variable. It is not an input field and is never stored in source, logs, or dataset output. PNG, JPEG and WebP uploads retain their actual image format.

The key has no expiry or lifetime usage quota; the account has unlimited wallet credits. General CAPTCHA service request throttling still applies. Credentials or billing failures stop the search; explicit invalid predictions can obtain a fresh image within the configured attempt limit. Keep the key private and do not include it in scheduled-task input.

#### Dataset charge limit

Apify may stop storing new dataset rows when the run's maximum total charge is reached. The Actor counts only stored rows, stops further dataset writes, and reports `isPartial: true` when that happens. A source result count is not a saved-record count. Check `OUTPUT_SUMMARY` and the dataset for the final stored count.

# Changelog

This Actor's version history is a separate document: https://apify.com/codingfrontend/ecourts-case-scraper/changelog.md

# Actor input Schema

## `caseNos` (type: `array`):

One or more CNR values with four letters followed by twelve digits. Duplicate values are looked up once.

## `maxCaptchaRetries` (type: `integer`):

Maximum CAPTCHA solver attempts in one browser session.

## `maxSessionAttempts` (type: `integer`):

Maximum fresh browser and proxy sessions for each unique CNR.

## `proxyCountryFallbacks` (type: `array`):

Country codes tried in order when Apify Proxy is used. Defaults to GB, US, then IN.

## `proxyConfiguration` (type: `object`):

Apify Proxy or custom proxy settings. Apify residential routing is the default.

## Actor input object example

```json
{
  "caseNos": [
    "KARC010037582023",
    "KABC010006152020"
  ],
  "maxCaptchaRetries": 3,
  "maxSessionAttempts": 30,
  "proxyCountryFallbacks": [
    "GB",
    "US",
    "IN"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset of verified eCourts case details.

## `runSummary` (type: `string`):

The OUTPUT_SUMMARY record in the run's default key-value store.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "caseNos": [
        "KARC010037582023",
        "KABC010006152020"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("codingfrontend/ecourts-case-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "caseNos": [
        "KARC010037582023",
        "KABC010006152020",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("codingfrontend/ecourts-case-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "caseNos": [
    "KARC010037582023",
    "KABC010006152020"
  ]
}' |
apify call codingfrontend/ecourts-case-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,codingfrontend/ecourts-case-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/fUbIlaJkbcVKaGtyU/builds/xOCstGj0kdr5a3rAn/openapi.json
