Congressional trading disclosure scraper and REST API
Project description
Congressional Trading Datastore
Scrapes, parses, and serves U.S. House financial disclosure (PTR) filings as a REST API with an interactive dashboard.
Installation
pip install congressional-trading
System dependency: This package requires pdftotext from Poppler:
# macOS
brew install poppler
# Debian/Ubuntu
sudo apt-get install poppler-utils
# Fedora
sudo dnf install poppler-utils
Quick Start (Local)
# Prerequisites: Python 3.12+, uv, pdftotext (poppler)
brew install poppler # macOS
# Install dependencies
uv sync
# Run the server
DATABASE_PATH=data/congressional_trades.db uv run uvicorn congressional_trading.main:app --reload --port 8080
- Dashboard: http://localhost:8080/dashboard
- API docs: http://localhost:8080/docs
- Health check: http://localhost:8080/api/v1/health
On first startup the scraper runs automatically if no recent scrape exists, pulling filings from 2020 to present.
Deployment
See docs/deployment.md for Railway production deployment instructions.
Environment Variables
| Variable | Default | Description |
|---|---|---|
DATABASE_PATH |
/data/congressional_trades.db |
SQLite DB path. Set to data/congressional_trades.db for local dev. |
LOG_LEVEL |
INFO |
Logging level |
SCRAPE_HOUR_UTC |
6 |
Hour (UTC) for the daily scrape cron job |
SCRAPE_START_YEAR |
2020 |
Earliest year to scrape filings from |
API Endpoints
All endpoints are prefixed with /api/v1. Rate limited to 10 req/sec.
Core
| Method | Path | Description |
|---|---|---|
| GET | /trades |
List trades. Requires ticker or member. Params: days, transaction_type, limit, offset |
| GET | /trades/summary |
Aggregate stats for a ticker. Params: ticker (required), days |
| GET | /members |
Members with recent trading activity. Params: days, limit, offset |
| GET | /health |
DB stats, last scrape time. Returns 503 if stale (>48h) |
Charts / Dashboard
| Method | Path | Description |
|---|---|---|
| GET | /trades/recent |
Recent trades for charting. Params: days, member, ticker, transaction_type |
| GET | /trades/trending |
Most-traded tickers with buy/sell breakdown. Params: days, limit |
| GET | /members/{member}/performance |
Member returns (30/60/90d) vs SPY with win rate |
| GET | /tickers/{ticker}/activity |
Ticker price history with congressional trade markers |
Dashboard UI
| Path | Description |
|---|---|
/dashboard |
Interactive HTML dashboard with charts (Plotly.js) |
Database Schema
SQLite with WAL mode. Four tables:
- filings — One row per House PTR filing. Tracks member info, filing date/year, processing status, retry count.
- trades — Individual transactions parsed from filings. Ticker, asset description, transaction type/date, amount range, owner.
- scraper_runs — Audit log of scrape cycles with counts and timing.
- price_cache — Cached stock closing prices from yfinance (ticker + date).
How the Scraper Works
- Downloads annual ZIP index files from
disclosures-clerk.house.gov - Parses the XML index to find PTR (Periodic Transaction Report) filings
- Downloads each PDF, extracts text with
pdftotext -layout - Parses columnar text into structured trade records
- Validates dates (rejects impossible years from PDF misalignment) and amounts
Runs daily at SCRAPE_HOUR_UTC via APScheduler. Includes rate limiting (1s between requests), circuit breaker (pauses after 5 consecutive failures), and retry logic (up to 3 attempts per filing).
Running Tests
uv run pytest tests/unit/test_parser.py -v
Project Structure
src/congressional_trading/
├── main.py # FastAPI app, lifespan, static files
├── config.py # Environment variables and constants
├── api/
│ ├── routes.py # Core API endpoints
│ └── chart_routes.py # Dashboard/chart endpoints
├── db/
│ ├── database.py # SQLite connection, schema, pragmas
│ ├── queries.py # All SQL queries
│ └── models.py # Pydantic response models
├── parser/
│ ├── ptr_parser.py # PDF text → structured trades
│ ├── patterns.py # Regex constants
│ └── xml_index.py # XML index parser
├── scraper/
│ ├── downloader.py # PDF download + text extraction
│ └── scheduler.py # APScheduler cron setup
└── services/
└── price_service.py # yfinance price fetching + caching
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file congressional_trading-0.1.0.tar.gz.
File metadata
- Download URL: congressional_trading-0.1.0.tar.gz
- Upload date:
- Size: 127.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1820a0835b9f5266aa9912b9048bbbcef214d10b727cafac7a5354c8ff88e830
|
|
| MD5 |
0a9ebf555e40c7179de9cbd090fcb17d
|
|
| BLAKE2b-256 |
7bcf75ff378e48d40908bfde335535a5bd153aa31f85eba4532b778e7b48db49
|
File details
Details for the file congressional_trading-0.1.0-py3-none-any.whl.
File metadata
- Download URL: congressional_trading-0.1.0-py3-none-any.whl
- Upload date:
- Size: 29.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
adfa150b3813b120dcd396878e8afd38c3da8d70fc64b63806f920b76fa5b670
|
|
| MD5 |
d055aac54f0f6f2d3ddb3829f55950f7
|
|
| BLAKE2b-256 |
220f2ae8d867fa96658a10bd2c90df5a2760528cf24123ac94f5e0f2f9c171b1
|