# CourtListener Scraper (`zerobreak/courtlistener-scraper`) Actor

CourtListener Scraper is a Python tool designed to extract legal opinions, court dockets, oral arguments, judge profiles, and case citations from CourtListener. It exports structured legal data into clean CSV or JSON formats for legal research and data analysis.

- **URL**: https://apify.com/zerobreak/courtlistener-scraper.md
- **Developed by:** [ZeroBreak](https://apify.com/zerobreak) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.99 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Court Records Scraper: US Case Law, Federal Dockets, Oral Arguments and Judges

<p align="center">
  <img src="https://imgur.com/lPU9l1X.png" alt="Court Records Scraper" width="800" />
</p>

Collect and organize publicly available US court records, including case law opinions, federal court dockets, oral arguments, judges, and court directory information. Export structured records to JSON, CSV, or Excel for legal research, litigation monitoring, and legal lead generation.

Search does not require a login. A free CourtListener account token is required only for the details mode.

Docket records can include parties, law firms, attorneys, nature of suit, and the assigned judge. Opinion records include citations, filing dates, judges, and PDF links when available. Oral argument records include audio links, recording duration, and file size.

### Use Cases

- **Legal lead generation:** Find federal lawsuits by keyword or nature of suit and organize associated parties, law firms, and attorneys.
- **Litigation monitoring:** Search company or brand names regularly to identify newly available federal cases.
- **Legal research:** Build structured collections of opinions with citations, courts, judges, and source references.
- **Journalism:** Research public court filings and oral arguments without a PACER account.
- **Judge analytics:** Collect judicial opinions, directory information, educational backgrounds, appointment dates, and positions when available.

### Supported Collection Modes

| Mode | Description |
|---|---|
| `opinions` | Search case law opinions and related case information. |
| `dockets` | Search federal RECAP docket records, including available filing information. |
| `oral_arguments` | Collect oral argument records and audio metadata. |
| `judges` | Search judge records and available background information. |
| `courts` | Collect court directory information. |
| `details` | Retrieve an individual opinion, cluster, or docket using its identifier and a free access token. |

### Input Parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `opinions` | Collection mode: `opinions`, `dockets`, `oral_arguments`, `judges`, `courts`, or `details`. |
| `queries` | array | `["web scraping"]` | Search queries, one per line. Supports CourtListener query syntax, including quoted phrases and AND/OR operators. |
| `courts` | array | Empty | Court IDs, such as `scotus`, `ca9`, or `nysd`. Values are combined into the court filter. |
| `filedAfter` | string | Empty | Include records filed on or after this date. Format: `YYYY-MM-DD`. |
| `filedBefore` | string | Empty | Include records filed on or before this date. Format: `YYYY-MM-DD`. |
| `orderBy` | string | `score desc` | Sort order: `score desc`, `dateFiled desc`, or `dateFiled asc`. |
| `ids` | array | Empty | Identifiers for details mode, such as `opinion:10822738`, `cluster:10356150`, or `docket:69510553`. |
| `includeRecapDocuments` | boolean | `true` | Include available RECAP filing information in docket records. |
| `maxItems` | integer | `100` | Maximum number of output rows for the run. Maximum: 5,000. |
| `apiToken` | string | Empty | Free CourtListener token, required only for details mode. Stored as a secret input. |
| `timeoutSecs` | integer | `300` | Maximum run duration in seconds. Rows already saved are retained when the run stops. |
| `requestTimeoutSecs` | integer | `30` | Timeout for an individual request. |

### Example Input

Search federal docket records for a specific phrase in the Southern District of New York:

```json
{
  "mode": "dockets",
  "queries": ["\"Blake Lively\""],
  "courts": ["nysd"],
  "filedAfter": "2024-01-01",
  "orderBy": "dateFiled desc",
  "includeRecapDocuments": true,
  "maxItems": 100,
  "timeoutSecs": 300,
  "requestTimeoutSecs": 30
}
```

### Output Structure

Every dataset row includes `recordKind` and the same value in `type`, allowing you to filter records from mixed collection runs. Search results also retain the query that found each record.

#### Example Opinion Record

```json
{
  "recordKind": "opinion",
  "type": "opinion",
  "clusterId": 10356150,
  "docketId": 69733181,
  "caseName": "State v. Clouser",
  "court": "Ohio Court of Appeals",
  "courtId": "ohioctapp",
  "dateFiled": "2025-03-13",
  "docketNumber": "114094",
  "citations": ["2025 Ohio 834"],
  "citeCount": 0,
  "judge": "E.T. Gallagher",
  "status": "Published",
  "url": "OPINION_PAGE_URL",
  "opinions": [
    {
      "id": 10822738,
      "type": "combined-opinion",
      "opinionKind": "combined-opinion",
      "perCuriam": false,
      "downloadUrl": "OPINION_PDF_URL",
      "snippet": "[Cite as State v. Clouser, 2025-Ohio-834.]"
    }
  ],
  "query": "\"web scraping\""
}
```

#### Record Types and Additional Fields

- **Opinion records:** Case name, court, filing date, docket number, citations, judge, publication status, and available opinion links.
- **Docket records:** Parties, law firms, attorneys, nature of suit, assigned judge, case identifier, and available RECAP documents.
- **Oral argument records:** Case name, audio URL, duration in seconds, and MP3 file size.
- **Judge records:** Judge name, educational background, political affiliations, and judicial positions when available.
- **Court records:** Short name, full name, citation format, jurisdiction, and current-use status.
- **Detail records:** Record category, source identifier, and the returned record data when a token is provided.

Failed queries do not stop the entire run. The actor saves an error row containing `error`, `errorMessage`, and `statusCode`, then continues. If details mode is used without a token, it records `TOKEN_REQUIRED` and skips the restricted request.

### Output Fields

| Field | Type | Description |
|---|---|---|
| `recordKind` | string | Record category: `opinion`, `docket`, `oral_argument`, `judge`, `court`, `detail`, or `error`. Also stored as `type`. |
| `caseName` | string | Case name on opinion, docket, and oral argument records. |
| `court` | string | Court name associated with the record. |
| `courtId` | string | Court identifier, such as `scotus` or `nysd`. |
| `dateFiled` | string | Filing date. |
| `docketNumber` | string | Court docket number. |
| `citations` | array | Reporter citations associated with an opinion. |
| `judge` | string | Judge information when available. May be empty if the source has no value. |
| `url` | string | Source record page or court website link. |
| `parties` | array | Party names associated with a federal docket. |
| `lawFirms` | array | Law firms associated with a docket, with duplicate spellings consolidated. |
| `attorneys` | array | Attorneys associated with a docket. |
| `recapDocuments` | array | Available filing numbers, summaries, dates, page counts, availability information, and document links. |
| `audioUrl` | string | Oral argument audio link. |
| `durationSec` | number | Oral argument duration in seconds. |
| `fileSizeMp3` | number | MP3 file size when available. |
| `name` | string | Judge or court directory name. |
| `schools` | array | Educational information associated with a judge, when available. |
| `positions` | array | Judicial positions, courts, appointing authorities, and confirmation or election dates when available. |
| `raw` | object | Returned detail record data, available when a token is provided. |
| `error` | string | Error code associated with a failed query or identifier. |
| `errorMessage` | string | Description of the failure. |
| `statusCode` | integer | Status code associated with a failed request. |

### Limits and Error Handling

#### Result Limits

The default maximum is 100 rows per run, with a hard cap of 5,000. Search pages contain up to 20 results, and the actor continues through subsequent pages until it reaches the configured cap or there are no more results.

Broad oral argument searches may match thousands of recordings. Increase `maxItems` as needed, while keeping the maximum of 5,000 in mind.

#### Request Pacing and Retries

Requests are paced at approximately one per second. Responses indicating rate limits or server errors are retried. When a `Retry-After` value is provided, the actor uses it to determine how long to wait before retrying.

#### Details Mode Requires a Token

Individual opinion, cluster, and docket detail records require a free CourtListener token. Without one, details mode writes a `TOKEN_REQUIRED` row and skips the restricted request.

Other collection modes do not require the token.

#### Data Coverage

Opinions cover a broad selection of state and federal courts. Dockets mode searches federal RECAP records, which depend on filings that have been contributed to the archive. The available docket collection is therefore not a complete record of every federal case.

When republishing collected information, credit the Free Law Project and respect applicable source terms and restrictions.

### FAQ

#### What is the difference between PACER and RECAP?

PACER is the federal courts' paid docket system. RECAP is an archive of PACER filings contributed to the Free Law Project. This actor searches publicly available RECAP records. It does not log into PACER or purchase court documents.

#### Does this include every state trial court docket?

No. Opinion records cover a wide range of state and federal courts, while docket mode focuses on federal RECAP records. Coverage depends on the records available in the archive.

#### Do I need a CourtListener token?

Not for opinions, dockets, oral arguments, judges, or the court directory. A free token is required only for details mode, which retrieves an individual opinion, cluster, or docket by identifier.

#### How many cases can one run return?

The default is 100 rows, and the maximum is 5,000. The actor stops requesting additional pages when it reaches the configured limit or the available results are exhausted.

#### Can I get the full opinion text?

Search records may include a snippet and a PDF link when one is available from the court. This actor records the link but does not download the PDF. Details mode can retrieve an individual record when a token is provided.

#### What happens when a search fails?

The actor writes an error row containing the error code, message, and status code, then continues processing other queries where possible.

### Trademark Notice

CourtListener, the Free Law Project, and their related names, logos, and trademarks belong to their respective owners. They are used in this documentation solely to identify the source of the data and do not imply affiliation, sponsorship, endorsement, or partnership.

### Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, sponsored by, or otherwise officially associated with CourtListener or the Free Law Project.

### Is Web Scraping Legal?

Collecting information that is already public is generally legal. Scraping is not the same thing as hacking, and there is no single law that bans it. The limits are the usual ones: do not break into accounts, do not take private or confidential data, and be careful with personal data and copyrighted works. A site's terms can also restrict how you access it. Facts such as a public name, price, or rating are not the same thing as republishing someone's article or photo.

This actor collects information from public pages. It does not log in and it does not bypass access controls.

For a longer explanation, see Apify's article [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/).

# Actor input Schema

## `mode` (type: `string`):

Which CourtListener record type to collect. Opinions, dockets, oral arguments, and judges use search. Courts lists the court directory. Details fetches one record by id and needs an API token.

## `queries` (type: `array`):

Supports CourtListener query syntax (quotes, AND/OR). One query per line. Used for opinions, dockets, oral arguments, and judges.

## `courts` (type: `array`):

CourtListener court ids, one per line, such as scotus, ca9, or nysd. They are joined with spaces into the court filter. Use courts mode to look up ids.

## `filedAfter` (type: `string`):

Only include records filed on or after this date, in YYYY-MM-DD form.

## `filedBefore` (type: `string`):

Only include records filed on or before this date, in YYYY-MM-DD form.

## `orderBy` (type: `string`):

Sort order for search. score desc ranks by relevance. dateFiled desc and dateFiled asc sort on the filing date.

## `ids` (type: `array`):

Details mode ids, one per line. Examples: opinion:10822738, cluster:10356150, docket:69510553.

## `includeRecapDocuments` (type: `boolean`):

On docket rows, keep the RECAP document list. Turn this off to store parties and firms without the filing list.

## `maxItems` (type: `integer`):

Free version cap: 5,000 per run. Search returns 20 results per API page.

## `apiToken` (type: `string`):

Free at courtlistener.com. Needed only for details mode. Sent as an Authorization token header. Leave blank for public search.

## `timeoutSecs` (type: `integer`):

Maximum seconds for the whole run. The actor stops cleanly and keeps rows already saved.

## `requestTimeoutSecs` (type: `integer`):

Seconds to wait for a single CourtListener response before retrying.

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

Optional proxy for CourtListener requests. The default sends traffic directly, with no Apify proxy.

## Actor input object example

```json
{
  "mode": "opinions",
  "queries": [
    "\"web scraping\""
  ],
  "courts": [
    "scotus",
    "ca9"
  ],
  "filedAfter": "2010-01-01",
  "orderBy": "score desc",
  "includeRecapDocuments": true,
  "maxItems": 100,
  "timeoutSecs": 300,
  "requestTimeoutSecs": 30,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `opinions` (type: `string`):

Case name, court, filing date, docket number, judge, cite count, and URL.

## `dockets` (type: `string`):

Case name, court, filing date, nature of suit, parties, and law firms.

## `oral_arguments` (type: `string`):

Case name, court, argument date, duration, and audio URL.

## `judges` (type: `string`):

Name, gender, date of birth, and CourtListener URL.

## `courts` (type: `string`):

Court id, short name, full name, jurisdiction, and in-use flag.

## `details` (type: `string`):

Token-backed opinion, cluster, and docket records, with the raw payload.

## `errors` (type: `string`):

Queries and ids that failed, with the error code and HTTP status.

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

Every row from the run, without a table view applied.

# 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 = {
    "queries": [
        "\"web scraping\""
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("zerobreak/courtlistener-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 = {
    "queries": ["\"web scraping\""],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("zerobreak/courtlistener-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 '{
  "queries": [
    "\\"web scraping\\""
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call zerobreak/courtlistener-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zerobreak/courtlistener-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/9lQkSfHztKbYADR2U/builds/Wc434tUdE7HFuha40/openapi.json
