πŸ›οΈ U.S. Senate Congress Trade Tracker avatar

πŸ›οΈ U.S. Senate Congress Trade Tracker

Pricing

from $3.00 / 1,000 transaction records

Go to Apify Store
πŸ›οΈ U.S. Senate Congress Trade Tracker

πŸ›οΈ U.S. Senate Congress Trade Tracker

Track every U.S. Senate member stock trade automatically. Clean, structured data from official disclosures β€” senator name, ticker, trade date, amount. Perfect for investors following congress trades & quant researchers. No PDF parsing needed.

Pricing

from $3.00 / 1,000 transaction records

Rating

0.0

(0)

Developer

Fatih Δ°lhan

Fatih Δ°lhan

Maintained by Community

Actor stats

1

Bookmarked

30

Total users

7

Monthly active users

6 days ago

Last modified

Share

U.S. Senate Trading Pipeline

A senator files a $250k purchase of defense stock the week before a major procurement vote. The filing lands quietly on the Senate EFD system.

This actor delivers that filing β€” and every other Senate PTR β€” as clean, deduplicated JSON within hours of the official disclosure. No third-party aggregators. Direct from the Senate eFD system.

Part of a set:

Who uses this

  • Retail traders tracking which senators are buying/selling before major legislation β€” defense before NDAA votes, pharma before drug pricing bills, tech before antitrust hearings
  • Fintech developers building portfolio tools, alert systems, or dashboards on top of STOCK Act data
  • Journalists and researchers monitoring congressional trading patterns β€” no account, no paywall, raw government data
  • Quiver Quantitative / Capitol Trades users who want the raw feed instead of a third-party UI

Why this instead of Quiver or Capitol Trades? They aggregate from the same source β€” the Senate eFD system. This actor pulls directly from it. No middleman, no subscription. You own the feed.


What it produces

One row per individual transaction reported in a Senate PTR:

{
"id": "a3f9c1...",
"politician": "Jane Example",
"transaction_date": "2026-03-16",
"filing_date": "2026-03-20",
"ticker": "LMT",
"asset_name": "Lockheed Martin Corporation",
"asset_type": "Stock",
"type": "buy",
"amount_min": 250001,
"amount_max": 500000,
"owner": "self",
"source_id": "257795ae-e1b2-411d-b562-8fe4c2a4f2a1|6",
"content_hash": "7c2e5b8d4f6a0c9e3b7d1fa3f9c1e2b8d47f60a1c5e93b2d8f7a4c6e0b1d9f3a",
"filing_type": "original",
"amendment_number": null,
"fetchedAt": "2026-03-20T18:04:11.000Z",
"lastModifiedAt": "2026-03-20T18:04:11.000Z",
"revisionCount": 0
}
FieldTypeNotes
idstringSHA-256 of politician|date|asset|amount|source_id β€” unique per row, changes if source_id changes
politicianstringFiler name as it appears on the PTR
transaction_dateYYYY-MM-DDTrade execution date
filing_dateYYYY-MM-DDDate the PTR was submitted
tickerstring | nullnull for bonds, municipals, structured notes
asset_namestringFull asset description
asset_typestringStock, Stock Option, Mutual Fund, Corporate Bond, etc.
type'buy' | 'sell'Normalized from source purchase/sale codes
amount_minintegerLower bound of reported amount range, USD
amount_maxinteger | nullUpper bound. null for unbounded "Over $X" disclosures
owner'self' | 'joint' | 'spouse' | 'child'Account owner per STOCK Act categories
source_idstringSource PTR's document id + row ordinal (<ptr_uuid>|<row_index>)
content_hashstringSHA-256 of politician|date|asset|type|amount_min|amount_max|owner (source_id excluded) β€” see "Duplicate transactions across filings" below
filing_type'original' | 'amendment' | nullRead from the PTR's "(Amendment N)" label. null only when unlabeled β€” never guessed
amendment_numberinteger | nullThe N in "(Amendment N)"; null for originals
fetchedAtstring (ISO 8601 UTC)When this row was first pulled from source. Immutable β€” never updated by a later re-fetch of the same, unchanged row
lastModifiedAtstring (ISO 8601 UTC)When this row's content last changed. Equal to fetchedAt until a revision is detected
revisionCountintegerHow many times this source row's content has changed since it was first seen. 0 if never revised

Same core schema as the House actor β€” records from both merge cleanly on field names and dedup semantics. amendment_number is Senate-only.

Duplicate transactions across filings

id is unique per row (it includes source_id), so rows never collide β€” but the same real-world trade can still appear under two different ids if it's reported in more than one source document (a duplicate filing, or an amendment that re-lists a transaction from the original). content_hash fingerprints only the trade's real-world content (source_id excluded), so both copies hash identically and you can find them.

We never drop or merge rows. A shared content_hash:

  • Same document (same source_id prefix): a legitimate separate transaction β€” e.g. two same-day tranches of the same purchase. Keep both.
  • Different documents: the same trade reported more than once. Summing across both double-counts it β€” reconcile by content_hash before aggregating.

Example: two purchases of the same structured note, same day, same amount bracket, in the same PTR β€” different source_id rows, keep both. Versus: the same 12 transactions appearing in two separate PTR documents filed the same day β€” same content_hash, different source_id prefixes; summing all 24 rows double-counts every trade.

Fetch timestamps and immutable history

The Senate eFD system can revise a PTR after it's first posted β€” a corrected amount, a fixed typo β€” with nothing on the source side flagging that it happened. fetchedAt is set once, the first time a row is pulled, and never changes after that, even across a revision. lastModifiedAt moves to the revision's fetch time when the source republishes a row with different content, and revisionCount counts how many times that's happened. Rows are never overwritten in place β€” a revision lands as a new row that carries fetchedAt forward from the prior version, so both stay in the dataset.

To use it: keep a snapshot of a prior pull and diff it against a fresh one. Where two rows share source_id but differ in content_hash, lastModifiedAt tells you when the value changed.


How it works

Search fetch Parse Transform Dedup Store
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Senate EFD │─▢│ JSON primary │─▢│ type, amount, │─▢│ SHA-256 │─▢│ Apify β”‚
β”‚ search-index β”‚ β”‚ HTML β”‚ β”‚ dates, owner, β”‚ β”‚ natural β”‚ β”‚ Dataset β”‚
β”‚ 100/page loop β”‚ β”‚ fallback β”‚ β”‚ ticker β”‚ β”‚ key β”‚ β”‚ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

1. Fetch. Pages through the Senate eFD search index (efts.senate.gov), 100 records per page, until the result set is exhausted for the configured date window.

2. Parse. JSON response is primary. If a page yields empty asset names across all rows (a known eFD quirk), the raw HTML is re-parsed as fallback.

3. Normalize. Source purchase/sale codes map to buy/sell; amount ranges, dates, and owner categories map to the canonical schema shared with the House actor.

4. Dedup + push. The natural key is hashed to a stable ID; duplicates across overlapping runs are dropped; a same-source_id row with a changed content_hash is logged as a revision and its revisionCount/lastModifiedAt updated; records land in the default Apify dataset.

All HTTP calls retry 3 times with exponential backoff and Β±25% jitter.


Input

FieldTypeDefaultDescription
fetchDaysBackinteger90Rolling window of PTRs to fetch (1–365)
fromDatestring (YYYY-MM-DD)β€”Explicit start date. Overrides fetchDaysBack
toDatestring (YYYY-MM-DD)todayExplicit end date

How to use

Apify Console (no code): set your date window, run. Results land in the dataset; export as JSON, CSV, or Excel.

API:

# Trigger a run
curl -X POST "https://api.apify.com/v2/acts/seralifatih~SENATE-ACTOR-SLUG/runs?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "fetchDaysBack": 30 }'
# Read the dataset
curl "https://api.apify.com/v2/datasets/<dataset-id>/items?token=YOUR_TOKEN&format=json"

Scheduled: senators must disclose within 45 days of a trade, and filings arrive continuously. A daily or every-6-hours schedule keeps the feed current.


Self-hosting

The pipeline also runs standalone as an Express API with SQLite storage, a cron scheduler, and queryable REST endpoints β€” see the GitHub repository for the self-hosted setup.


Data source

U.S. Senate Electronic Financial Disclosures (eFD) β€” a public government database. Senate PTR filings are required under the STOCK Act of 2012 and are public domain.

This actor does not scrape third-party aggregators. It pulls only from the official source.


License

MIT. Use the actor or the source however you want.