# U.S. Senate Financial Disclosures Scraper (`automation-lab/us-senate-financial-disclosures-scraper`) Actor

Search official Senate eFD reports and export structured stock transactions, annual assets, liabilities, positions, agreements, and filing metadata.

- **URL**: https://apify.com/automation-lab/us-senate-financial-disclosures-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.01 / 1,000 item extracteds

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?

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

## U.S. Senate Financial Disclosures Scraper

Export official U.S. Senate financial disclosures from
[Senate eFD](https://efdsearch.senate.gov/) as structured dataset rows.
The Actor searches periodic transaction reports (PTRs) and annual reports,
opens the original filing, and flattens its useful tables for analysis.

Use it to:

- monitor newly submitted Senator stock-trade reports;
- export ticker, asset, transaction type, date, and amount ranges;
- collect annual assets, liabilities, positions, agreements, and other entries;
- feed public-disclosure research into a spreadsheet, database, or data pipeline;
- process one known eFD report URL without searching the full filing index.

The source is the official Senate eFD website.
This Actor covers Senator filings, not House Clerk disclosures.

### What does the U.S. Senate Financial Disclosures Scraper do?

For search inputs, the Actor:

1. establishes a permitted Senate eFD public-search session;
2. accepts the source's public-use agreement;
3. searches the official report index using your filer, state, report-type, and submission-date filters;
4. follows annual or PTR report links;
5. turns each source table row into a typed dataset item;
6. stops at `maxReports` or `maxItems`, whichever limit is reached first.

For `startUrls`, it skips index discovery and extracts the supplied report pages.
Report-type and ticker filters still apply to explicit URLs.

The Actor uses an Apify datacenter proxy because Senate eFD rejects direct
cloud requests. It rotates only during bounded session bootstrap and does not
automatically fall back to residential proxy traffic.

### Who is this Actor for?

#### Compliance and ethics researchers

Build repeatable extracts of public filing data while retaining the report ID,
official URL, filer, submission date, and source section for traceability.

#### Financial journalists

Find recent PTR transactions, identify disclosed tickers, and link every row
back to the official filing before reporting.

#### Market and policy analysts

Compare disclosed transaction activity with annual assets or other public
financial interests in downstream notebooks and databases.

#### Transparency projects

Schedule a narrow search as an Apify Task and compare report IDs or dataset
rows with an earlier run in your own workflow.

### What data can you extract?

| Field | Meaning |
| --- | --- |
| `recordType` | `transaction`, `annual_entry`, or a fallback `report_summary` |
| `reportType` | `periodic_transaction` or `annual` |
| `reportId` | Stable UUID from the official report URL |
| `reportTitle` | Filing title displayed by Senate eFD |
| `reportUrl` | Official Senate eFD detail URL |
| `submittedDate` | Filing submission date from the report search |
| `firstName`, `lastName` | Filer name fields from search results |
| `filerName` | Full filer label displayed by eFD |
| `section` | Source section, such as Transactions or Part 3. Assets |
| `itemNumber` | Row number when supplied by the report |
| `transactionDate` | Date of a PTR transaction |
| `owner` | Disclosed owner or debtor |
| `ticker` | Security ticker when disclosed |
| `assetName` | Asset or security description |
| `assetType` | Source asset or entry type |
| `transactionType` | Purchase, Sale, Exchange, or another source value |
| `amount` | Public value, income, liability, or transaction range |
| `comment` | Filing-row comment when present |
| `annualFields` | All labeled columns from the annual-report row |
| `scrapedAt` | ISO timestamp for extraction time |

Missing source values are returned as `null`.
Annual sections have different columns, so `annualFields` preserves all
section-specific labels while common values are also copied into columns such
as `assetName`, `owner`, and `amount`.

### Getting started

1. Open the Actor input page in Apify Console.
2. Choose `Periodic transaction reports`, `Annual financial disclosures`, or both.
3. Optionally enter a Senator name or two-letter state.
4. Set a submission date range.
5. Keep the first run small with `maxReports: 3` and `maxItems: 10`.
6. Click **Start**.
7. Open the default dataset to preview or export JSON, CSV, Excel, XML, or RSS.
8. Check `reportUrl` whenever your analysis needs the original public filing.

A practical first input is:

```json
{
  "lastName": "Wyden",
  "reportTypes": ["periodic_transaction"],
  "submittedDateFrom": "2026-01-01",
  "submittedDateTo": "2026-08-10",
  "maxReports": 3,
  "maxItems": 5
}
```

### Input parameters

#### `startUrls`

Optional official report URLs matching one of these shapes:

```text
https://efdsearch.senate.gov/search/view/ptr/<uuid>/
https://efdsearch.senate.gov/search/view/annual/<uuid>/
```

Other domains and general search-page URLs are rejected.

#### `firstName` and `lastName`

Optional Senate eFD filer-name filters.
Names are passed to the official search rather than matched against unrelated
page text.

#### `state`

Optional two-letter state code such as `OR`, `TX`, or `NY`.
Leave it empty to search all states.

#### `reportTypes`

Choose one or both values:

- `periodic_transaction` for PTR transaction rows;
- `annual` for annual disclosure table entries.

The default is both report types.

#### `submittedDateFrom` and `submittedDateTo`

Inclusive report submission dates in `YYYY-MM-DD` format.
They default to January 1 of the current year and today.
These dates filter report submissions, not the transaction date inside a PTR.

#### `tickers`

Optional ticker symbols such as `AMCR`.
Ticker filtering applies only to periodic transaction rows because annual
entries do not consistently expose a ticker column.

#### `maxReports`

Maximum detail pages to inspect.
The default is 25 and the allowed range is 1–1,000.

#### `maxItems`

Maximum output rows to save.
The default is 100 and the allowed range is 1–10,000.

### Output example

A current PTR can produce a record like this:

```json
{
  "recordType": "transaction",
  "reportType": "periodic_transaction",
  "reportId": "5ecc9b5c-07c1-4ec1-bd4a-2db759eff299",
  "reportTitle": "Periodic Transaction Report for 08/09/2026",
  "reportUrl": "https://efdsearch.senate.gov/search/view/ptr/5ecc9b5c-07c1-4ec1-bd4a-2db759eff299/",
  "submittedDate": "2026-08-08",
  "filerName": "Wyden, Ron (Senator)",
  "section": "Transactions",
  "itemNumber": 1,
  "transactionDate": "2025-04-30",
  "owner": "Spouse",
  "ticker": "AMCR",
  "assetName": "BERY - Berry Global Group, Inc. (Exchanged) Amcor plc Ordinary Shares (Received)",
  "assetType": "Stock",
  "transactionType": "Exchange",
  "amount": "$100,001 - $250,000",
  "comment": null
}
```

The Actor reports source ranges exactly as disclosed.
It does not infer an exact trade value from a range.

### How much does it cost to extract U.S. Senate financial disclosures?

The Actor uses pay-per-event pricing:

- a **$0.001** one-time start event per run;
- one `item` event for each dataset row;
- current item rates range from **$0.0019263 on FREE** to **$0.00046901 on DIAMOND**;
- the current BRONZE item rate is **$0.001675**.

Examples at the current BRONZE rate:

| Output rows | Start | Items | Estimated total |
| ---: | ---: | ---: | ---: |
| 5 | $0.001 | $0.008375 | $0.009375 |
| 25 | $0.001 | $0.041875 | $0.042875 |
| 100 | $0.001 | $0.1675 | $0.1685 |

The estimate covers Actor event charges.
Apify plan allowances and platform billing rules can affect the amount shown to
a particular account.
Rows rejected by your ticker filter are not saved or charged as item events.

### Search and monitoring workflows

#### Watch recent PTR submissions

Create a Task with a short submission-date window, schedule it, and compare
`reportId` plus row content against your own previous export.
The Actor does not send alerts or maintain a cross-run history by itself.

#### Review one official report

Pass its annual or PTR URL in `startUrls`.
This is useful when another system already discovered the filing link.

#### Build a spreadsheet export

Run the Actor, open the dataset, and select CSV or Excel.
Common normalized fields appear as columns; annual section-specific columns
remain available in `annualFields`.

#### Enrich a research database

Use `reportId`, `itemNumber`, and `section` as source context.
Keep `reportUrl` so reviewers can inspect the original filing.

### API access with cURL

Start a run:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~us-senate-financial-disclosures-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "reportTypes": ["periodic_transaction"],
    "lastName": "Wyden",
    "maxReports": 3,
    "maxItems": 10
  }'
```

For production scripts, prefer the `Authorization: Bearer` header so tokens do
not appear in URLs or shell history.

### API access with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor(
  'automation-lab/us-senate-financial-disclosures-scraper'
).call({
  reportTypes: ['annual'],
  lastName: 'Murphy',
  maxReports: 1,
  maxItems: 25,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### API access with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor(
    "automation-lab/us-senate-financial-disclosures-scraper"
).call(run_input={
    "reportTypes": ["periodic_transaction"],
    "state": "OR",
    "maxReports": 5,
    "maxItems": 50,
})

items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
```

### Use with Apify MCP

#### Setup for Claude Code

Add this Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/us-senate-financial-disclosures-scraper"
```

#### Setup for Claude Desktop, Cursor, or VS Code

Claude Desktop, Cursor, and VS Code can use this MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/us-senate-financial-disclosures-scraper"
    }
  }
}
```

Example prompts:

- "Find recent Senate PTR filings for Wyden and return at most 20 rows."
- "Extract this official Senate eFD annual report URL into structured entries."
- "Get annual disclosure assets submitted this year for Senator Murphy."

### Integrations

Use Apify integrations to send dataset rows to:

- Google Sheets for review;
- Make or Zapier for downstream workflows;
- webhooks when a run finishes;
- cloud storage or a database through the dataset API;
- notebooks and BI tools through JSON, CSV, or Excel exports.

Deduplication and change detection should use your destination system or a
separate workflow step.

### Limits and source behavior

- Senate eFD may block direct requests and individual proxy identities.
- The Actor rotates a bounded number of datacenter sessions during bootstrap.
- A failed bootstrap ends with a non-zero run status rather than returning a
  misleading empty dataset.
- Search results cover public Senator filings available through eFD.
- The source can remove older reports under its retention rules.
- Paper or attachment-only content may not expose table rows.
- A valid no-result search succeeds with an empty dataset.
- Tickers are not present for every disclosed asset.
- `maxItems` can stop extraction partway through a report.

### Tips for reliable runs

- Start with a narrow date range and small limits.
- Use a last name or state when you need only one filer group.
- Increase `maxReports` before increasing `maxItems` if the first reports contain
  few matching rows.
- Remove a ticker filter when testing whether the search itself found reports.
- Keep the official `reportUrl` in downstream exports.
- Schedule at a considerate interval; public filings do not require constant polling.

### Responsible use and legality

The Actor accesses public government disclosure pages.
You are responsible for complying with Senate eFD terms, applicable law, Apify
policies, and restrictions on how financial disclosure information may be used.

Do not use the data for harassment, identity theft, unlawful profiling, or to
misrepresent a disclosed range as an exact amount.
Validate important findings against the linked official report.
This Actor is a technical extraction tool and does not provide legal, financial,
or investment advice.

### Troubleshooting

#### Why did the run fail before returning rows?

The source may have rejected all bounded proxy sessions or changed its agreement
or search page. Retry later once. If failures persist, inspect the run log rather
than treating the failure as a valid empty result.

#### Why is the dataset empty?

Check the submission dates, name, state, report types, and ticker filter.
A ticker filter excludes annual entries and PTR rows without that exact ticker.

#### Why is an annual field only inside `annualFields`?

Annual sections use different columns.
The Actor maps common values to `assetName`, `owner`, `assetType`, and `amount`
and preserves every labeled source column in `annualFields`.

#### Does this Actor cover House disclosures?

No. Use the related House Actor for House Clerk PTR data.

#### Does it download PDFs or attachments?

No. It extracts the searchable digital annual and PTR table pages.

### FAQ

#### Can I search by transaction date?

Not directly. The date inputs filter report submission dates.
Use `transactionDate` downstream after extracting PTR rows.

#### Can I use a report URL from another domain?

No. `startUrls` accepts only official `efdsearch.senate.gov` annual and PTR
report URLs.

#### Are amount ranges converted to numbers?

No. The source's public range is retained as text to avoid false precision.

#### Are records charged if they do not match my ticker filter?

No. Only rows written to the dataset use the `item` event.

#### Can I schedule this Actor?

Yes. Save a working input as an Apify Task and add a schedule.
The Actor itself does not persist prior-run state or send alerts.

### Related automation-lab Actors

- [House Stock Trades Scraper](https://apify.com/automation-lab/house-stock-trades-scraper)
  extracts House Clerk PTR transactions from public filings.
- [Senate Lobbying Disclosure Scraper](https://apify.com/automation-lab/senate-lobbying-disclosure-scraper)
  covers public lobbying registrations and activity reports, not personal
  financial disclosure filings.

Use each Actor for its stated source and filing system rather than combining
House, Senate eFD, and lobbying records as though they shared one schema.

# Actor input Schema

## `startUrls` (type: `array`):

Optional official eFD annual or periodic transaction report URLs. When supplied, search filters are skipped but report type and ticker filters still apply.

## `firstName` (type: `string`):

Optional first-name filter used by the Senate eFD report search.

## `lastName` (type: `string`):

Optional last-name filter, such as Wyden. Leave blank to include all senators.

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

Optional two-letter U.S. state code. Leave blank to include every state.

## `reportTypes` (type: `array`):

Extract periodic transaction reports, annual financial disclosures, or both.

## `submittedDateFrom` (type: `string`):

Optional inclusive filing submission date in YYYY-MM-DD format. Defaults to January 1 of the current year.

## `submittedDateTo` (type: `string`):

Optional inclusive filing submission date in YYYY-MM-DD format. Defaults to today.

## `tickers` (type: `array`):

Optional ticker symbols for periodic transaction rows, such as AMCR. Annual disclosure entries do not match a ticker filter.

## `maxReports` (type: `integer`):

Maximum report detail pages to inspect before stopping.

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

Maximum matching transaction or annual disclosure rows to save.

## Actor input object example

```json
{
  "startUrls": [],
  "lastName": "Wyden",
  "reportTypes": [
    "periodic_transaction"
  ],
  "submittedDateFrom": "2026-01-01",
  "submittedDateTo": "2026-08-10",
  "tickers": [],
  "maxReports": 3,
  "maxItems": 10
}
```

# Actor output Schema

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

Dataset containing all extracted disclosure rows.

# 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 = {
    "startUrls": [],
    "firstName": "",
    "lastName": "Wyden",
    "state": "",
    "reportTypes": [
        "periodic_transaction"
    ],
    "submittedDateFrom": "2026-01-01",
    "submittedDateTo": "2026-08-10",
    "tickers": [],
    "maxReports": 3,
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/us-senate-financial-disclosures-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 = {
    "startUrls": [],
    "firstName": "",
    "lastName": "Wyden",
    "state": "",
    "reportTypes": ["periodic_transaction"],
    "submittedDateFrom": "2026-01-01",
    "submittedDateTo": "2026-08-10",
    "tickers": [],
    "maxReports": 3,
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/us-senate-financial-disclosures-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 '{
  "startUrls": [],
  "firstName": "",
  "lastName": "Wyden",
  "state": "",
  "reportTypes": [
    "periodic_transaction"
  ],
  "submittedDateFrom": "2026-01-01",
  "submittedDateTo": "2026-08-10",
  "tickers": [],
  "maxReports": 3,
  "maxItems": 10
}' |
apify call automation-lab/us-senate-financial-disclosures-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/us-senate-financial-disclosures-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/qqcg3gHPbIkkp19IF/builds/sUXAfWuIkyzBHdRUY/openapi.json
