I set out to answer a simple question: which stocks did members of Congress trade last quarter? Every one of those trades is public. The STOCK Act makes members file a Periodic Transaction Report for each one. I figured I would pull the data in an evening and move on.
I was wrong about the evening, and being wrong is the reason this turned into a product.
The filings live on two separate portals, one for the House and one for the Senate, each with its own search form built for looking up a single document at a time. There is no developer API on either side. So step one was already two scrapers instead of one.
Then I opened the actual filings. A meaningful share of them are scanned images. Not text, not tables, pictures of paper that somebody photographed and uploaded. To get a ticker and an amount out of those, you run OCR and then you fix what the OCR got wrong. Member names are spelled inconsistently across filings. Tickers hide inside long asset descriptions. Amounts are not numbers at all; they are brackets like "$1,001 to $15,000," because that is all the law requires anyone to disclose.
I spent an afternoon hand-correcting OCR output for a single member's year of trades. At the end I had a clean spreadsheet for one person, and the next reporting cycle had already landed.
Sitting in that mess, I almost closed the tab. Then it clicked: the reason a clean version of this data did not already exist as a simple API was sitting right in front of me. The tedium was the whole point. Anybody can scrape a well-behaved JSON endpoint. Almost nobody wants to babysit OCR across two government portals and reconcile inconsistent names, so almost nobody had.
That is a moat. Not a clever one, a boring one. The annoying, un-glamorous part of the problem was the part worth owning.
So I built the collection and cleaning once, properly, and turned it into a queryable dataset: filter by member, by ticker, or by date range, get one clean row per transaction back. Each row carries the member, the asset, the transaction type, the amount bracket, the dates, and a filing ID that points back to the exact source document, so any number can be checked.
Three groups, and they turned up quickly once the data was clean.
Reporters doing accountability work, the kind of investigative journalism that runs on "who traded what, and when." A member-watch query returns one name's full year with brackets and filing IDs, ready to fact-check.
Compliance and ESG teams screening a watchlist. They run a set of tickers or members on a schedule and route the hits into a review, exactly the kind of compliance and ESG check that used to mean an intern and a stack of PDFs.
And quants, quietly testing whether disclosed trades carry any signal at all. They just want the whole record as rows.
I put these in the docs, not in the fine print, because getting them wrong wastes someone's afternoon the way it wasted mine.
The reports lag the actual trades by 30 to 45 days under the filing deadline, so this is research data, not a live feed. Amounts are ranges, never exact values, because exact values do not exist in the source. And rows that came through OCR from a scanned filing are flagged as such, so when a number really matters you can spot-check it against the original PDF.
The instinct as a builder is to look for the clean problem: the nice API, the tidy dataset, the thing you can wire up in an evening. But if you can wire it up in an evening, so can everyone else, and there is no reason it should be yours.
The problems worth building on are often the ones that made you want to quit halfway through. The OCR, the two portals, the inconsistent names: that friction is not in the way of the business, it is the business. I would not have believed that before the afternoon that nearly killed the project.
If you want to see the finished version, it runs on Apify as the Congress Financial Disclosures and Stock Trades API, billed per transaction returned (a 100-row member query runs about $0.19, a full 1,000-row pull about $1.91, with a cap you set). The track a single member's trades and pull a year of disclosures examples are the two I reach for most. I also wrote up the technical walkthrough on Medium if you want the how rather than the why.
Happy to answer anything about the OCR cleanup or the pricing math in the comments.
Congrats on building this — I actually love the story behind it. A lot of valuable data products start with exactly this kind of painful manual cleanup that most people would never want to do.
One thing I’d pay attention to is making the user outcome extremely clear. The dataset itself is interesting, but the first question a potential customer may have is: “How does this help me make better decisions, research faster, or uncover insights I couldn’t get easily before?”
I’d also make the target user crystal clear upfront. Investors, journalists, researchers, and developers may all find this valuable, but each one will connect with a different benefit.
The data work is impressive, and I suspect there are some positioning opportunities that could help more visitors immediately understand the value behind it.
If useful, I do a $10 homepage audit where I document messaging friction points and practical copy improvements.