SEC Insider Trades — EDGAR Form 4 Buys & Sells as JSON avatar

SEC Insider Trades — EDGAR Form 4 Buys & Sells as JSON

Pricing

from $8.50 / 1,000 insider filing parseds

Go to Apify Store
SEC Insider Trades — EDGAR Form 4 Buys & Sells as JSON

SEC Insider Trades — EDGAR Form 4 Buys & Sells as JSON

Track corporate insider trading from SEC EDGAR. Give a ticker or CIK; get normalized Form 4/3/5 insider transactions as JSON: who traded (officer, director, 10% owner), buy/sell/grant/exercise, shares, price, value, shares held after, and dates. Deterministic parsing of public SEC data.

Pricing

from $8.50 / 1,000 insider filing parseds

Rating

0.0

(0)

Developer

Scott Helvick

Scott Helvick

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 hours ago

Last modified

Share

Corporate insiders — officers, directors, and 10% owners — must report every trade in their own company's stock to the SEC on Form 4 (and Form 3/5), but the filings are buried in EDGAR as raw ownership XML with cryptic single-letter transaction codes. Give this Actor a ticker or CIK and it returns the recent insider filings as clean, normalized JSON: who traded, whether it was a buy or a sell, how many shares, at what price, what they own now, and when.

What this does

  • Resolves a stock ticker (e.g. AAPL, BRK.B) or 10-digit CIK to the issuer via SEC's official ticker map.
  • Reads the issuer's EDGAR filing history and selects the recent Form 4 (changes in ownership), Form 3 (initial holdings), and/or Form 5 (annual) filings you ask for.
  • Fetches each filing's structured ownership XML and parses it deterministically — no LLM, no guesswork — into one dataset record per filing.
  • Decodes the SEC transaction code into a human-readable type: open-market purchase / sale, grant/award, option exercise, gift, tax withholding, and the rest of the Form 4/5 code table.
  • Captures both the non-derivative table (common stock) and the derivative table (options, RSUs, warrants) with underlying security, exercise price, and expiration.
  • Identifies the reporting owner and their relationship (director, officer + title, 10% owner) so you can tell an executive's trade from a passive holder's.
  • Adds a per-filing summary: transaction count, total acquired (buy) value, total disposed (sell) value, and net share change — for quick scanning.
  • Bounds cost and runtime with maxFilings (per company) and an optional sinceDate floor.

Use it to:

  • Monitor a watchlist of tickers for new insider buying or selling since a given date.
  • Flag cluster buys — several insiders at one company purchasing in a short window.
  • Track a specific executive's acquisitions and dispositions over their recent filings.
  • Feed an investment-research agent structured insider-activity data without writing an EDGAR parser.
  • Build an ownership-change dataset across a set of companies for downstream analysis.

Why deterministic parsing matters

The data is already public and free — SEC publishes every Form 4 as machine-readable XML. The problem isn't access; it's that the raw document is awkward to consume: transaction amounts are nested several elements deep, buys and sells are distinguished by a one-letter code (P, S, A, M, F, G, …) plus a separate acquired/disposed flag, and options live in a wholly separate table with their own schema.

Insider-trade figures are the kind of data people act on, so the extraction has to be exact. Every value this Actor returns is copied verbatim from the filing's XML — share counts, prices, and post-transaction holdings are the filer's own reported numbers, and the only interpretation layer is mapping the SEC's documented transaction codes to readable labels. There is no language model in the path to hallucinate a number. That also keeps the cost floor near zero, so the price reflects the normalization work, not an inference bill.

How it compares to the alternatives

ApproachNormalized fieldsCodes decodedPer-filing aggregatesDerivativesAgent-callable
Raw EDGAR XML / full-text searchraw only— (you parse it)
Generic web scraper on a finance sitepartialsometimesinconsistentbrittle
SEC Insider Tradesyesyesyesyesyes

Raw EDGAR is authoritative but unstructured — you own the parsing, the code table, and the derivative-table edge cases. A scraper pointed at a third-party finance site inherits that site's layout changes and gaps. This Actor goes straight to the primary source and returns a stable, documented JSON shape.

Input

FieldTypeRequiredDefaultDescription
identifiersarray of stringsyesTickers or 10-digit CIKs (1–50). Tickers resolve to CIK via SEC's official map; BRK.B/BRK-B variants are handled.
formTypesarray of strings["4"]Which ownership forms to include: 4 (changes — buys/sells), 3 (initial holdings), 5 (annual). Validated at runtime.
maxFilingsinteger20Max filings per company, newest first (1–100). Bounds runtime and cost (one charge per filing).
sinceDatestringOptional ISO date floor (YYYY-MM-DD); only filings filed on/after are returned. Blank = most recent regardless of date.

One dataset record is produced per filing. Filings come from the issuer's recent EDGAR history (the latest ~1000 filings); deep historical archives beyond that window are out of scope.

Output

One record per insider filing. Nullable fields are null on a failed record.

{
"identifier": "AAPL",
"status": "completed",
"cik": "0000320193",
"issuerName": "Apple Inc.",
"issuerTicker": "AAPL",
"formType": "4",
"filingDate": "2026-05-29",
"periodOfReport": "2026-05-27",
"accessionNumber": "0001140361-26-023363",
"reportingOwner": {
"name": "LEVINSON ARTHUR D",
"cik": "0001214128",
"isDirector": true,
"isOfficer": false,
"isTenPercentOwner": false,
"isOther": false,
"officerTitle": null,
"relationship": "Director"
},
"transactions": [
{
"securityTitle": "Common Stock",
"transactionDate": "2026-05-27",
"transactionCode": "S",
"transactionType": "Open-market sale",
"acquiredDisposed": "D",
"shares": 50000,
"pricePerShare": 311.02,
"transactionValue": 15551000.0,
"sharesOwnedAfter": 3764576,
"directOrIndirect": "D",
"isDerivative": false,
"underlyingSecurity": null,
"underlyingShares": null,
"exercisePrice": null,
"expirationDate": null
}
],
"summary": {
"transactionCount": 1,
"totalAcquiredValue": 0.0,
"totalDisposedValue": 15551000.0,
"netShares": -50000
},
"sourceFilingUrl": "https://www.sec.gov/Archives/edgar/data/320193/000114036126023363/form4.xml",
"error": null,
"notice": "Figures are from public SEC EDGAR filings (see sourceFilingUrl); parsing is best-effort and provided as-is, not investment advice — verify against the primary filing before relying on any value."
}

A failed record carries status: "failed" and an error tag (e.g. unresolved-identifier, no-insider-filings, xml-fetch-failed) with transactions: [].

Example

Input — latest 10 insider transactions at each of two companies, since a date:

{
"identifiers": ["AAPL", "NVDA"],
"formTypes": ["4"],
"maxFilings": 10,
"sinceDate": "2026-01-01"
}
curl -X POST "https://api.apify.com/v2/acts/shelvick~sec-insider-trades/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"identifiers":["AAPL","NVDA"],"formTypes":["4"],"maxFilings":10,"sinceDate":"2026-01-01"}'
from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("shelvick/sec-insider-trades").call(
run_input={"identifiers": ["AAPL", "NVDA"], "formTypes": ["4"], "maxFilings": 10}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["issuerTicker"], item["reportingOwner"]["relationship"], item["summary"])

Calling from an AI agent

Apify MCP server (mcp.apify.com) — the Actor is exposed as a callable tool whose input schema is self-documenting, so an LLM can construct a valid call from the tool description alone (ticker or CIK in; normalized insider filings out). Pay per call via x402 (USDC on Base) or Skyfire managed tokens.

Apify SDK (Python)from apify_client import ApifyClient, then client.actor("shelvick/sec-insider-trades").call(run_input=...) and iterate the dataset (see the example above).

REST APIPOST /v2/acts/shelvick~sec-insider-trades/run-sync-get-dataset-items?token=... for synchronous runs; the async /runs endpoint for large multi-company pulls that may exceed the 5-minute sync window.

Pricing

Pay-per-event, billed only on success: one charge per insider filing that is fetched and parsed, after that record is pushed to the dataset. Companies that don't resolve, and filings that can't be retrieved or parsed, are free. Because billing is per filing, maxFilings is also your spend cap — a quick latest-activity scan is a handful of charges; a deep multi-company pull scales linearly and is bounded by your run's max-charge setting.

See the Pricing tab on this Store page for the current per-event rate and any active subscriber discounts.

Design notes: www.scotthelvick.com/tools/sec-insider-trades

Behavior

Run-level failures (rare) — input validation only: an empty identifiers list, more than 50 identifiers, an unknown value in formTypes, or maxFilings out of the 1–100 range are rejected before any work.

Per-record outcomes (common) — each company/filing yields a record; failures are isolated and never charged:

  • unresolved-identifier — the ticker/CIK didn't resolve in SEC's map.
  • no-insider-filings — the company has no filings of the requested form type(s) in the recent window.
  • submissions-fetch-failed / xml-fetch-failed — SEC returned an HTTP error for the filing list or a document.
  • xml-parse-failed / not-an-ownership-document — the document wasn't parseable ownership XML.

Performance — requests are paced under SEC's ~10 requests/second fair-access ceiling. Cost is one filing-list fetch per company plus one document fetch per filing, so wall-clock scales with total filings: a single company at the default maxFilings finishes in a few seconds; a 50-company pull at depth runs longer and may need the async endpoint rather than the 5-minute sync window.

FAQ

Do you charge for a company with no insider filings? No. A company that doesn't resolve, or has no filings of the requested type, returns a failed record and is not charged. You only pay per filing actually fetched and parsed.

How do I get just buys, or just sells? The Actor returns all transactions in each filing; filter on transactions[].transactionCode (P = purchase, S = sale) or acquiredDisposed (A/D) in your own code. The per-filing summary already separates acquired vs disposed value.

Why is a price 0 on some transactions? Grants, gifts, and certain exempt transactions have no market price — they're reported with a zero or absent price-per-share. Those rows still appear, with transactionValue of 0 or null.

How far back can I go? The Actor reads the issuer's recent EDGAR filing window (the latest ~1000 filings) and takes the newest maxFilings after any sinceDate. Deep historical archives beyond that window aren't fetched in this version.

Can I pass a CIK instead of a ticker? Yes — any mix of tickers and 10-digit CIKs (zero-padding optional). CIKs skip the ticker-map lookup.

What this doesn't do

  • No real-time alerting. It returns the current state of recent filings on demand; it isn't a streaming feed or a push notifier.
  • No analysis or signals. It returns the transactions as filed — no buy/sell scoring, sentiment, or recommendations. It is not investment advice.
  • No Form 13D/13F or institutional holdings. This is insider ownership (Forms 3/4/5), not activist stakes or fund holdings.
  • No full historical backfill. Only the recent EDGAR filing window, not the entire multi-decade archive.
  • No deduplication of amended filings. Amendments are returned as their own records; reconcile them yourself if needed.

For standardized company financial statements (income statement, balance sheet, cash flow) from SEC XBRL, use a fundamentals-normalization Actor instead. For company enforcement and litigation history, use a regulatory-records profiler. For arbitrary page-to-JSON extraction from non-EDGAR sources, use a structured-extraction Actor.