# Maryland Eviction Cases - Docket Events & Removals (`j0401/md-evictions`) Actor

Maryland's residential eviction docket (public open data, 794,432 events across 462,359 cases, 2022-today): event date and type, case number and case type, county, tenant city/state/ZIP, and the eviction date on the rows where a tenant was removed. Filter by county, case type or event type.

- **URL**: https://apify.com/j0401/md-evictions.md
- **Developed by:** [Wenhao Yang](https://apify.com/j0401) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.03 / 1,000 maryland eviction docket events

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

## Maryland Eviction Cases - Docket Events & Removals

Maryland's residential eviction docket, straight from the Maryland Judiciary.
**794,432 docket events across 462,359 cases**, from January 2022 through the
last closed month.

### Low cost

**From $0.00005 per record, down to $0.00003 at Gold.** Pay only for the
records you actually receive - the whole register stays queryable, you are
never billed for the scan behind it.

### What you get

One row per docket event, with the case attached to it:

- **The event** - its date and type (a petition filed, a warrant served, a
  cancellation, an eviction) and the event comment
- **Who was evicted** - the tenant's city, state and ZIP
- **The case** - the case number and the case type (failure to pay rent,
  tenant holding over, wrongful detainer, breach of lease)
- **The court** - the county / jurisdiction and the location
- **The removal** - the eviction date, on the rows where a tenant was actually
  removed

#### A row is an event, not an eviction

The three counts are different, and all three are real:

- **794,432 rows** - docket **events** (a case contributes several).
- **462,359 distinct case numbers** - the **cases**.
- **66,958 rows with an eviction date** - the tenant was actually **removed**.

Set `evictedFrom` to narrow to the third - it keeps only the removal rows and
drops the rest.

### Filter it

- **County** - `county="Baltimore City"`, `county="Montgomery"`. 24
  jurisdictions in total.
- **Case type** - Failure to Pay Rent (764,542 events, plus 11 more in a
  spelling variant the filter also matches), Tenant Holding Over, Wrongful
  Detainer, Breach of Lease. Matched case-insensitively.
- **Event type** - an exact-set match (`eventType="Petition - For Warrant of
  Restitution Filed"`; the accepted values are listed in the input schema). To
  find the **removals**, use `evictedFrom` (above) rather than `eventType`,
  which needs the full value `Warrant of Restitution - Return of Service -
  Evicted` to hit them.
- **Case number** - `caseNumber` is a substring match, so a stored number
  such as `caseNumber="D-01-LT-26-106033-016"` returns that one case's events;
  a shorter prefix (e.g. the base `D-01-LT-26-106033`) spans every docket number
  beneath it.
- **Tenant city and ZIP**.
- **Date range** on the event date, and on the eviction date.

### Example inputs

**The removals** - cases where a tenant was actually evicted since January.

```json
{ "evictedFrom": "2026-01-01", "maxResults": 50 }
```

**One county's docket** - combine county and case type.

```json
{ "county": "Baltimore City", "caseType": "Failure to Pay Rent", "maxResults": 50 }
```

**Every event on one case** - the case number is the case key.

```json
{ "caseNumber": "D-01-LT-26-106033-016" }
```

**Where the filings are** - `mode=aggregate` returns one count row per county;
every group comes back.

```json
{ "mode": "aggregate", "groupBy": "county" }
```

### Or roll it up

Set `mode=aggregate` and get a rolled-up count by **county**, **event type**,
**case type**, **year**, **eviction year** or **city**. Every group comes
back - not cut off by `maxResults`.

### Then follow the cases

- Eviction filings and removals by county, month over month.
- Every docket event on one case, in order.
- Failure-to-pay-rent vs. tenant-holding-over, side by side.
- Which ZIPs see the most removals.

### Example output

**One removal** - `county=Baltimore City`, `evictedFrom=2026-01-01`:

```json
{
 "platform": "md-evictions",
 "source": "maryland-eviction-docket",
 "mode": "rows",
 "groupKey": "",
 "groupCount": "",
 "groupBy": "",
 "eventDate": "2026-08-27T00:00:00.000",
 "eventType": "Warrant of Restitution - Return of Service - Evicted",
 "eventComment": "",
 "county": "Baltimore City",
 "location": "Civil",
 "tenantCity": "BALTIMORE",
 "tenantState": "MD",
 "tenantZip": "21206",
 "caseType": "Failure to Pay Rent",
 "caseNumber": "D-01-LT-26-106033-016",
 "evictedDate": "2026-08-25T00:00:00.000",
 "eventYear": "2026",
 "evictionYear": "2026",
 "sourceUpdatedAt": "2026-09-29"
}
```

**`mode=aggregate`, `groupBy=county`** - one count row per jurisdiction:

```
Baltimore                       279,094
Baltimore City                  152,234
Prince George's                 139,738
Montgomery                       60,757
Anne Arundel                     52,639
Howard                           24,532
```

### Notes on the data, from the source

- **Event, case, and eviction are three different things.** See above.
- **`evictionYear` is empty on most rows.** It is set only on the events that
  led to a removal (66,958 of 794,432); use `year` (the event year) as the
  general time dimension.
- **Two ways to find a removal, 24 rows apart.** `evictedFrom` matches the
  **66,958 rows with an eviction date**; `eventType` set to the full value
  `Warrant of Restitution - Return of Service - Evicted` matches **66,982** -
  a few eviction-event rows carry no date. `evictedFrom` is the safer key.
- **A few case types and event types have source spelling variants** (e.g.
  `Breach Of Lease` as well as `Breach of Lease`). The filters match
  case-insensitively so a query catches both.
- **The register is refreshed monthly**; `sourceUpdatedAt` carries the
  dataset's own refresh date.
- **Tenant city names are as the court recorded them** and are not normalized
  (`BALTIMORE` and `Baltimore` both appear), so a substring match is the right
  way to search.

# Actor input Schema

## `county` (type: `string`):

Substring match on the county or jurisdiction, e.g. 'Baltimore', 'Montgomery', "Prince George's". 24 jurisdictions in total. Blank = any.

## `location` (type: `string`):

Substring match on the location label the court recorded, e.g. 'Baltimore City'. Blank = any.

## `city` (type: `string`):

Substring match on the tenant's city, e.g. 'Baltimore', 'Laurel'. Blank = any.

## `zip` (type: `string`):

Exact 5-digit tenant ZIP code, e.g. '21206'. Blank = any.

## `caseNumber` (type: `string`):

Substring match on the case number, e.g. 'D-01-CV-22'. Returns every docket event on the matching cases. Blank = any.

## `caseType` (type: `string`):

Exact case type, matched case-insensitively so the source's own spelling variants are caught. 'Failure to Pay Rent' dominates (764,542 events). Blank = any.

## `eventType` (type: `string`):

Exact docket event type (the four values below), matched case-insensitively. To find the removals use evictedFrom instead of this - it matches the rows that carry an eviction date. Blank = any.

## `eventFrom` (type: `string`):

Earliest docket event date, YYYY-MM-DD. Blank = any.

## `eventTo` (type: `string`):

Latest docket event date, YYYY-MM-DD. Blank = any.

## `evictedFrom` (type: `string`):

Earliest eviction (removal) date. Setting this narrows the results to the rows where a tenant was actually removed and drops the rest. Blank = any.

## `evictedTo` (type: `string`):

Latest eviction (removal) date. Blank = any.

## `recentDays` (type: `integer`):

Only events whose event date falls within the last N days. Ignored when 'Event on or after' is set. 0 = off.

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

rows = docket events matching your filters (default). aggregate = one count row per group (see groupBy).

## `groupBy` (type: `string`):

Which dimension to aggregate over (mode=aggregate). Blank = county. Every group is returned - aggregate mode is not cut off by maxResults.

## `maxResults` (type: `integer`):

Cap the number of records pushed in rows mode (0 = default 50; up to 2,000 per run). Each record is metered individually, so there is no per-run charge cap. Aggregate mode returns every group.

## Actor input object example

```json
{
  "county": "",
  "location": "",
  "city": "",
  "zip": "",
  "caseNumber": "",
  "caseType": "",
  "eventType": "",
  "eventFrom": "",
  "eventTo": "",
  "evictedFrom": "",
  "evictedTo": "",
  "recentDays": 0,
  "mode": "rows",
  "groupBy": "",
  "maxResults": 50
}
```

# Actor output Schema

## `recordsUrl` (type: `string`):

Maryland eviction case events - as JSON

## `datasetUrl` (type: `string`):

No description

## `runUrl` (type: `string`):

No description

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("j0401/md-evictions").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("j0401/md-evictions").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 '{}' |
apify call j0401/md-evictions --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,j0401/md-evictions"
        }
    }
}
```

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/DH65qtC10GmskJGNL/builds/F0itF4ZSdcK3RoE0F/openapi.json
