Quick answer
An SEC Form 4 reports insider transactions — an officer, director or major holder buying, selling, being awarded, or exercising options on their own company's stock.
Most EDGAR tooling stops at the filing index: form type, date, accession number, filer. That tells you a Form 4 exists. It does not tell you what was traded.
The trades live one layer deeper, in the filing's <ownershipDocument> XML. That is what the SEC Form 4 Insider Trades Scraper parses — one row per trade, not per filing.
One filing is many transactions 📊
This is the modelling decision that matters. A single Form 4 routinely contains several line items: an option exercise, the sale that funds the tax on it, and a residual holding — three different transaction codes, three different prices, one filing.
Flatten that to one row per filing and you have destroyed the data. You cannot answer "how many shares did this insider actually sell" from a filing-level row, because the filing does not have a single share count.
So: one row per buy, sell, award or exercise line item, each carrying its own transaction code, share count, price, and post-transaction holding.
Joint filings need every owner attributed 👥
Form 4 supports multiple reporting owners on one filing — a trust and its trustee, spouses, an entity and its control person. Attributing the whole transaction to the first name in the XML overstates that person's activity and erases the others.
Every reporting owner is resolved and attributed to their share of each transaction. It is the sort of correctness that never shows up in a demo and matters enormously if you are building a signal on top.
Footnotes are where the honest nulls live 🧾
Form 4 leans on footnotes. A price is frequently reported as a range or "see footnote 3", rather than a number in the price field.
There are two ways to handle that. You can guess — parse the footnote text, take a midpoint, put a number in the column. Or you can report null and preserve the footnote.
We report null. A fabricated price in a financial dataset is worse than a missing one, because a missing value announces itself and a plausible wrong number does not. Anyone building on this can decide their own footnote policy; they cannot un-guess ours.
SEC's polite-use ceiling is a shared budget ⏱️
SEC asks for roughly 10 requests per second and a descriptive User-Agent with contact details. Ignore either and you get blocked — not by anti-bot defences, but by a stated fair-access policy that is entirely reasonable.
The subtlety is that the ceiling is per requester, not per run. Two concurrent runs each pacing themselves to 10 req/s together make 20. So the request-interval floor is shared across runs rather than held per-process, and 429/5xx retry with exponential backoff honouring Retry-After.
What a row looks like
Issuer name, ticker and CIK; reporting owner name, CIK and relationship (officer, director, ten-percent owner); transaction date and code; share count; price per share; acquired-or-disposed flag; shares owned following the transaction; derivative or non-derivative; and the accession number linking back to the filing.
Who this is for 🎯
- Quant and signal research — insider buying clusters as a factor input.
- Compliance and surveillance — monitoring named insiders across issuers.
- Financial media — spotting notable trades as they file.
- Investor relations — tracking a peer group's insider activity.
The honest limitations 🚧
- Form 4 only. Forms 3 and 5 are a different shape and out of scope here.
- A trade appears when it is filed, not when it is executed — Form 4 allows a reporting delay.
- Footnote-only prices are
nullby design, not by omission. - Ticker-to-CIK resolution depends on SEC's own mapping; a very recent listing may not resolve yet.
Pricing
$0.20 per run plus $0.0025 per transaction row — $2.70 per 1,000.
→ SEC Form 4 Insider Trades Scraper on Apify
Built by Devil Scrapes. We handle the XML under the filing, the joint filings that need every owner attributed, and the footnote prices we refuse to guess at.
Top comments (0)