# Legacy.com Obituary Scraper (`crawlerbros/legacy-com-scraper`) Actor

Scrape obituaries from Legacy.com - the largest online obituary archive in the US. Search obituaries by name or keyword, browse recent obituaries by state, fetch full obituary pages by URL, and get deceased name, birth/death dates, age, city/state, full obituary text, photos, and guest book visits.

- **URL**: https://apify.com/crawlerbros/legacy-com-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Automation, News, Agents
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Legacy.com Obituary Scraper

Scrape **Legacy.com** — the largest online obituary archive in the United States, hosting millions of obituaries published by newspapers, funeral homes, and families. Search obituaries by name or keyword, browse recent obituaries by US state, or fetch any obituary page by URL — and get the deceased's name, birth and death dates, age, city and state, the full obituary text, photos, and guest book visit counts. Pure HTTP, no login, no cookies, no proxy required.

### What this actor does

- **Three modes:** `search`, `browseByState`, `byUrl`
- **Full obituary records:** name, birth/death dates, age, city/state, full text, photos
- **State browsing:** scan recent obituaries and keep only those located in a chosen US state
- **Filters:** death-date range, contains-keyword, max pages scanned
- **Photo galleries:** photo URL plus all gallery photos when published
- **Empty fields are omitted**

### Data source

Data is served from **obits.legacy.com**, the obituary platform behind Legacy.com's "Legacy" obituary pages (`https://www.legacy.com/legacy/<slug>`). Search and browse pages are public HTML; each obituary page embeds structured JSON-LD data (name, dates, address, full text, photos) plus guest book visit counts. No authentication, cookies, or paid infrastructure is used.

### Output per obituary

- `obituaryId` — Legacy.com's internal obituary UUID
- `name`, `givenName`, `familyName` — deceased's full name and parts
- `birthDate`, `deathDate` — ISO dates (`YYYY-MM-DD`)
- `age` — age at death, derived from birth/death dates when both are present
- `city`, `state` — location from the obituary's address (2-letter US state code)
- `headline` — e.g. `Jean Smith Obituary 2026`
- `description` — short obituary description
- `genre`, `articleSection` — content category labels from the embedded article metadata
- `obituaryText` — the full obituary text (paragraphs separated by blank lines)
- `datePublished`, `dateCreated`, `dateModified` — publication timestamps (date part)
- `photoUrl` — the obituary's main photo
- `galleryPhotoUrls[]` — all photos from the obituary's photo gallery
- `guestBookVisits` — the guest book visit counter shown on the page
- `sourceUrl` — canonical Legacy.com URL of the obituary
- `recordType: "obituary"`, `scrapedAt`

In `search` and `browseByState` modes every emitted record is the **full** obituary detail record above. If an obituary detail page cannot be loaded (rare — page not yet on the obituary platform), the record falls back to the listing fields `name`, `deathDate`, `photoUrl`, `snippet`, and `sourceUrl`; no `null` fields are ever emitted.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` / `browseByState` / `byUrl` |
| `searchQuery` | string | `smith` | Free-text query matching name or obituary text (mode=search) |
| `state` | string | `TX` | US state filter — browse recent obituaries (mode=browseByState) or filter search results by state |
| `obituaryUrls` | array | – | Full obituary URLs to fetch (mode=byUrl) |
| `dateRangeFrom` | string | – | Keep obituaries with death date ≥ this ISO date |
| `dateRangeTo` | string | – | Keep obituaries with death date ≤ this ISO date |
| `containsKeyword` | string | – | Keep obituaries whose name/headline/text contains this substring |
| `maxItems` | int | `50` | Hard cap on emitted records (1–1000) |
| `maxPages` | int | `10` | Max result/feed pages to scan, 10 results per page (1–500) |
| `proxyConfiguration` | object | off | Optional Apify proxy, engaged only if blocked |

#### Example: search by name

```json
{
  "mode": "search",
  "searchQuery": "smith",
  "maxItems": 20
}
```

#### Example: browse recent obituaries in Texas

```json
{
  "mode": "browseByState",
  "state": "TX",
  "maxItems": 10,
  "maxPages": 20
}
```

#### Example: date-range filtered search

```json
{
  "mode": "search",
  "searchQuery": "patricia",
  "dateRangeFrom": "2026-01-01",
  "dateRangeTo": "2026-12-31",
  "maxItems": 30
}
```

#### Example: fetch specific obituaries by URL

```json
{
  "mode": "byUrl",
  "obituaryUrls": [
    "https://www.legacy.com/legacy/osea-ocasio",
    "https://www.legacy.com/legacy/karen-todd"
  ]
}
```

### Limitations

- **US obituaries only** — the actor targets the obituaries served by obits.legacy.com. Legacy.com's newspaper-branded and international properties use different page structures.
- **No direct state search** — the obituary search index has no state filter, so `browseByState` scans the most recent obituaries (up to `maxPages` × 10) and keeps those in the chosen state. Older obituaries may require more pages to find.
- **Detail-page fallback** — if an obituary detail page cannot be loaded (rare — page not yet on the obituary platform), the record is emitted with the listing fields only (`name`, `deathDate`, `photoUrl`, `snippet`, `sourceUrl`).
- **Per-record completeness varies** — not every obituary publishes birth dates, photos, or full text; missing values are omitted, never filled with placeholders.
- **Guest book visits** — only the visit counter shown on the page is collected; guest book entries themselves are not scraped.

### Use cases

- **Genealogy research** — bulk-export obituary records with dates, locations, and full text for family-history projects
- **Death-notice monitoring** — watch for obituaries of specific people or in specific states
- **Legal & probate** — collect proof-of-death notices published by families and funeral homes
- **Funeral-industry intelligence** — analyze obituary volume, locations, and publication patterns
- **Journalism** — find and verify obituary details for reporting
- **Academic research** — assemble structured datasets of US death notices

### FAQ

**What is the data source?** Obituaries are fetched from obits.legacy.com, the platform that serves Legacy.com's obituary pages. This is a third-party actor using the public website — it is not affiliated with Legacy.com.

**Is a proxy or login required?** No. The public pages are served without cookies or authentication. An optional proxy is available as a fallback if the source starts blocking requests.

**What does `browseByState` do?** The obituary search index does not expose a state filter directly, so this mode scans the most recent obituaries (up to `maxPages` × 10 pages) and keeps only those whose obituary address lists the chosen state. The more recent the obituaries you need, the fewer pages are needed. The same state value can also narrow `search` results — the filter is applied whenever a state is set.

**How fresh is the data?** Search and browse modes surface the most recently published obituaries first, so data is typically same-day fresh for new deaths.

**Why are some fields missing on some records?** Not every obituary publishes every piece of information — e.g. some obituaries omit birth dates or photos. Missing values are simply omitted from the record; nothing is filled with placeholder values.

**What date formats are accepted for `dateRangeFrom` / `dateRangeTo`?** ISO `YYYY-MM-DD` (e.g. `2026-01-01`). Death dates are compared at day granularity.

**Can I scrape obituaries from other Legacy.com locales?** This actor targets US obituaries served by obits.legacy.com. Legacy.com's newspaper-branded and international properties use different page structures.

**Does this actor collect obituary photo URLs only, or the photo files?** It collects the public photo URLs (they load without any special headers). Downloading the images themselves is up to your pipeline.

**What if my search returns nothing?** Try fewer filters, a broader `searchQuery`, or raise `maxPages`. Zero results is reported in the run's status message and the run still succeeds.

# Actor input Schema

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

What to fetch.

## `searchQuery` (type: `string`):

Free-text query matching the deceased name or obituary text (mode=search).

## `state` (type: `string`):

US state filter. In mode=browseByState, scans recent obituaries and keeps only those whose address is in this state. In mode=search, also keeps only results whose address is in this state. Leave empty to disable.

## `obituaryUrls` (type: `array`):

Full obituary URLs, e.g. `https://www.legacy.com/legacy/osea-ocasio` (mode=byUrl).

## `dateRangeFrom` (type: `string`):

Only keep obituaries whose death date is on or after this date (ISO `YYYY-MM-DD`).

## `dateRangeTo` (type: `string`):

Only keep obituaries whose death date is on or before this date (ISO `YYYY-MM-DD`).

## `containsKeyword` (type: `string`):

Only keep obituaries whose name, headline, or obituary text contains this substring (case-insensitive).

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

Hard cap on emitted records.

## `maxPages` (type: `integer`):

Maximum number of result/feed pages to scan (10 results per page). Higher values find more results but take longer.

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

Optional Apify proxy. The actor first tries a direct connection and only engages the proxy if the source blocks the request.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "smith",
  "state": "TX",
  "obituaryUrls": [],
  "dateRangeFrom": "",
  "dateRangeTo": "",
  "containsKeyword": "",
  "maxItems": 50,
  "maxPages": 10,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `obituaries` (type: `string`):

Dataset containing all scraped obituaries.

# 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 = {
    "mode": "search",
    "searchQuery": "smith",
    "state": "TX",
    "obituaryUrls": [],
    "dateRangeFrom": "",
    "dateRangeTo": "",
    "containsKeyword": "",
    "maxItems": 50,
    "maxPages": 10,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/legacy-com-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 = {
    "mode": "search",
    "searchQuery": "smith",
    "state": "TX",
    "obituaryUrls": [],
    "dateRangeFrom": "",
    "dateRangeTo": "",
    "containsKeyword": "",
    "maxItems": 50,
    "maxPages": 10,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/legacy-com-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 '{
  "mode": "search",
  "searchQuery": "smith",
  "state": "TX",
  "obituaryUrls": [],
  "dateRangeFrom": "",
  "dateRangeTo": "",
  "containsKeyword": "",
  "maxItems": 50,
  "maxPages": 10,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call crawlerbros/legacy-com-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/legacy-com-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/GkRTcECMFfaV3sYs0/builds/pwfYZG6Dei32K2xkh/openapi.json
