Tony Wang7 min readHow to Scrape Congressional Stock Disclosures in 2026 (API & Python)
Get congressional stock-disclosure filings from the House Clerk and Senate eFD in 2026 — structured JSON by member, ticker, or date range, plus parsed reports.
Congressional stock-disclosure data is a case where the underlying records are unambiguously public — members of Congress are legally required to file them — but getting them into a usable shape takes real work. The House Clerk and the Senate each run their own disclosure portal, with their own search fields and their own PDF-based filings, and neither exposes a unified, structured API. This guide covers the DIY approach to both portals and where it breaks, no-code options, and a structured API that normalizes both chambers into one schema and parses individual filings into structured JSON.
Why scrape congressional stock disclosures?
Congressional financial-disclosure data powers:
- Public-interest transparency and journalism — track what members and candidates for federal office have disclosed buying or selling, and when, against votes, committee assignments, or legislative activity.
- Compliance and conflict-of-interest research — flag disclosed trades in sectors a member's committee oversees, for watchdog groups, academic researchers, and newsrooms.
- Trend and coverage research — see how disclosure volume and filing types shift by chamber, state, or election cycle over time.
- Filing-timeliness tracking — periodic transaction reports carry a required filing window, and due-date-extension filings are themselves a signal worth tracking.
- Cross-referencing market data — pair a disclosed ticker with a live quote from Yahoo Finance or Google Finance for the context around a disclosed trade.
Is it legal to scrape congressional disclosures?
Option 1: DIY in Python (and why it breaks)
A DIY scraper has to hit two unrelated systems and reconcile them yourself:
import requests
from bs4 import BeautifulSoup
# House Clerk: search returns an HTML results page, not JSON
house = requests.get(
"https://disclosures-clerk.house.gov/PublicDisclosure/FinancialDisclosure",
headers={"User-Agent": "Mozilla/5.0 (compatible; research-bot/1.0)"},
)
soup = BeautifulSoup(house.text, "html.parser")
# Each result links out to a separate PDF — no structured fields, no ticker
# Senate eFD requires a session/search form and returns its own HTML shape,
# entirely unrelated to the House Clerk's markup or fields
Where it takes real engineering time:
- Two portals, two schemas. The House Clerk and Senate eFD each have their own search parameters, their own result markup, and no shared identifiers — every field you want has to be mapped and normalized separately per chamber.
- The filings themselves are PDFs. Search results point to a PDF of the actual disclosure; individual disclosed trades — ticker, transaction type, date, amount range — live inside that document, not in the search results, so you still have to fetch and parse every PDF.
- PDF layout varies. Filings aren't a fixed template across members, years, or filing type — periodic transaction reports, annual reports, and blind-trust filings lay out differently, and some older or lower-volume filers' PDFs are scanned images rather than text.
- No ticker-level search across chambers. Neither portal's own search lets you query "every disclosed trade in ticker X across House and Senate" in one call — you'd need to pull broadly and filter client-side after parsing every PDF.
Option 2: No-code tools
A handful of dashboards and marketplace scrapers surface congressional trading data, mostly by re-scraping the same two portals and republishing a subset of fields. They save a one-off lookup, but they don't solve the parsing problem — you still don't get a structured, per-trade record straight from the source PDF, and most don't cover due-date-extension or blind-trust filing types at all.
Option 3: A structured Congress API
Crawlora's Congressional Stock Disclosures API normalizes both the House Clerk and Senate eFD into one search shape, and parses an individual filing's PDF into structured JSON. Search by member, ticker, or date range:
curl "https://api.crawlora.net/api/v1/congress/stock-disclosures?chamber=house&last_name=pelosi&from=2025-01-01&to=2025-12-31" \
-H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"count": 4,
"filings": [
{
"member": "Pelosi, Nancy",
"office": "California, District 11",
"chamber": "house",
"filing_year": 2025,
"filing_type": "periodic_transaction",
"pdf_url": "https://disclosures-clerk.house.gov/public_disc/ptr-pdfs/2025/20025123.pdf"
}
]
}
}
Then pull a Senate filing the same way and parse both in Python:
import requests
h = {"x-api-key": "YOUR_API_KEY"}
base = "https://api.crawlora.net/api/v1/congress"
results = requests.get(f"{base}/stock-disclosures", headers=h, params={
"chamber": "senate", "ticker": "AAPL", "election_year": 2024,
"sort": "filing_year", "direction": "desc", "page": 1, "limit": 20,
}).json()["data"]["filings"]
pdf_url = results[0]["pdf_url"]
report = requests.get(f"{base}/report", headers=h, params={"url": pdf_url}).json()["data"]
stock-disclosures accepts chamber (house or senate), member or separate first_name/last_name, state, district, ticker, filer_type, election_year, and a from/to date range, and can be sorted by name, office, or filing_year in either direction, paged with page and limit. report takes a filing's pdf_url and returns the parsed disclosure — real fields and schema in the docs — instead of a document you'd otherwise open and read by hand. Store one row per filing, keyed by pdf_url, and re-run the search on a schedule to catch newly filed disclosures.
What you can collect
Public congressional financial-disclosure data across both chambers: filing search results (member name, office/state/district, chamber, filing year, normalized filing type, and the PDF URL of the original document) filterable by member, state, district, ticker, filer type, and election year; and parsed report content from an individual filing's PDF. Filing types cover annual, periodic transaction, due-date-extension, blind-trust, and other — periodic transaction reports are the ones disclosing individual trades within a reporting window.
Limitations and common challenges
- Two source systems, reconciled into one shape. House Clerk and Senate eFD publish independently — expect normal source-side lag or formatting differences between chambers even after normalization.
- Report parsing depends on the underlying PDF. Layout varies by filing type and filer, and some older or lower-volume filers' disclosures are scanned images rather than text — parsing quality tracks the source document's own quality.
- Not real-time. These are periodic filings with a legally required filing window under the STOCK Act, not a live trade feed — there's an inherent lag between a disclosed transaction and when it's filed and published.
- Ticker coverage varies by report type. How individual holdings appear differs by filing type — pair a ticker search with the report endpoint to parse the underlying document rather than relying on search alone.
- Public data only, not investment advice. This collects what members and candidates already publicly disclosed under legal requirement — never a signal to trade on, and never a way to infer anything beyond what was actually filed.
Where this gets used
- Transparency journalism — track disclosed trades against committee assignments, votes, or legislative activity.
- Watchdog and compliance research — monitor filing timeliness and flag disclosures in sectors a member's committee oversees.
- Academic and political research — study disclosure patterns by chamber, state, or election cycle over time.
- Cross-source financial research — pair a disclosed ticker with live pricing from Yahoo Finance or Google Finance.
Sources
Start collecting
Try it first, free: run any public URL through the Free Web Scraper, or check whether a site blocks bots with the Anti-Bot Checker — no signup.
Test the stock-disclosures search and report endpoints in the Playground, check the schema in the API docs, and review pricing. Congressional disclosures tell you what a member or candidate officially reported and when; SEC EDGAR covers the same disclosure-driven pattern for public companies, and Yahoo Finance or Google Finance add the live price and market context around a disclosed ticker — pair the disclosure with market data instead of reading either in isolation. See also how to choose a web scraping API and is web scraping legal.
Part of our how-to-scrape guide series — every platform we cover, in one index.
Frequently asked questions
How do I search congressional stock disclosures with an API?
Send a member name — or a ticker, chamber, state, or year filter — as query parameters to Crawlora's /congress/stock-disclosures endpoint and get normalized filing rows back: member, office, filing year, filing type, and the PDF URL of the original document, as structured JSON.
Where does this data come from, and does it cover both chambers?
Both. Pass chamber=house or chamber=senate — House disclosures come from the House Clerk's public site and Senate disclosures from the Senate eFD system, the two official filing portals. These are public records that members of Congress are legally required to file; Crawlora normalizes the two different systems into one response shape.
Can I search by stock ticker?
The search endpoint accepts a ticker filter alongside member, state, district, filer type, and year. How individual holdings appear varies by report type, so pair a ticker search with the report endpoint to parse the underlying document.
Which report types are available?
annual, periodic_transaction, due_date_extension, blind_trust, and other. Periodic transaction reports are the ones that disclose individual trades within a reporting window.
Is this investment advice?
No. This is a public-records API for research, journalism, and compliance work. Crawlora is not an investment adviser, and how you publish or act on congressional disclosure data is your responsibility under applicable law.