# SEC Form 4 Insider Trading Scraper: Buys & Sells (`automation_craft/sec-form-4-insider-trading-scraper`) Actor

Pull SEC Form 4 insider trades by ticker, CIK, insider name or the whole market, back to 2003, no login or API key: 100 rows in 19 seconds. Each row is one transaction line: code, shares, price, value, holding after, roles, footnotes, Rule 10b5-1 flag. JSON or CSV, pay per row.

- **URL**: https://apify.com/automation_craft/sec-form-4-insider-trading-scraper.md
- **Developed by:** [Automation Craft](https://apify.com/automation_craft) (community)
- **Categories:** Business, Developer tools, News
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.38 / 1,000 insider transactions

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### SEC Form 4 Insider Trading Scraper: Buys & Sells

**SEC Form 4 insider trading** data as one row per transaction line: who traded, in which company, the SEC transaction code, the date, shares, price, value and the holding after, by ticker, CIK, insider or the whole market, with no login, no API key and no proxy setting.

This Actor reads the ownership filings insiders send to the SEC (Form 4, and Forms 3 and 5 on request) from the SEC's own keyless EDGAR hosts: the EDGAR full-text search to list the filings, then each filing's own ownership XML, one request per filing. Insider filings are XML from 2003-06-30, so a company's or an insider's history reaches back to mid 2003. Every row carries the insider's roles and title, the line's own footnotes with their text, the Rule 10b5-1 trading plan checkbox and any mention of the rule, the derivative terms of option and unit lines, every reporting owner of a joint filing, quality flags and a signal score from a fixed formula. Use it as an insider trading API for your own code (curl, Node and Python examples below), as a scheduled feed of open market buys, or as a CSV export for a spreadsheet. This Actor is an independent tool: it is not affiliated with or approved by the U.S. Securities and Exchange Commission (SEC).

#### Why this one

- **Pay per row delivered, plus a small start fee per run.** An unknown ticker, a name that matches no company, a filing that is not found, a line your filters leave out, a status row, a company summary and a cluster buy row cost nothing, and every miss is named in a free row.
- **One row per line, not per filing.** A Form 4 with five sales gives five rows, in the filing's own order, each with its own footnotes (`footnotes` with `id` and `text`, and `footnoteIdsByField` to say which value a note explains).
- **Companies, insiders or the whole market.** Tickers, company CIKs or exact listed names; insider CIKs or names across every company they reported for; filings by accession number or EDGAR link; or every Form 4 filed in a date window.
- **Planned trades flagged.** `rule10b5_1Checked` is the checkbox of filings from April 2023 on, `rule10b5_1Mentioned` is a mention of Rule 10b5-1 in the line's footnotes or the remarks, and `isPlannedTrade` is either. Filter with `rule10b5_1` (only planned trades, or leave them out).
- **The holding around the trade.** `sharesOwnedAfter` as filed, `sharesOwnedBefore` and `ownershipChangePercent` worked out from the line (common stock lines), `isNewPosition`, and every holding line of the filing attached to the row as `holdings`, free.
- **Fast and polite.** On the platform at 256 MB the prefill (the 20 newest rows of Apple, NVIDIA and Tesla) took 2 to 4 seconds and the newest 100 rows of the whole market took 19 seconds (2026-11-02). The SEC is asked at most 4 times per second, under its fair access limit of 10, with a declared User-Agent.

### Quick start

1. Put one or more stock tickers into **Company tickers** (the prefill is `AAPL`, `NVDA`, `TSLA`). For a company without a ticker use **Company CIK numbers**; for one person across every company, use **Insider CIK numbers** or **Insider names**.
2. Or leave every target empty to read every Form 4 filed in the last 7 days (the whole market).
3. Optional: pick a **Preset** such as Open market buys, or set **Transaction codes**, **Minimum value (USD)**, **Insider roles** or **Rule 10b5-1 trading plans**.
4. Optional: turn on **Company summaries** or **Cluster buys** (free rows at the end of the run).
5. Set **Maximum rows** (the prefill is 20; 100 is used when the field is left out) and click **Start**. Rows appear in the Dataset tab; export JSON, CSV or Excel, or read them through the API.

### Use cases

- **Insider buying screens:** the Open market buys preset over the market week, with `minTransactionValue` and Cluster buys to find companies where several insiders bought within a few days.
- **Watching your holdings:** a list of tickers on an Apify schedule with `daysBack` or `maxAgeHours`, sorted by value in the `SORTED-ROWS` record.
- **One insider across companies:** a director's or a fund's CIK in `insiderCiks` gives every line they reported, at every company, back to 2003.
- **Planned selling:** the Planned sales preset lists sales under a Rule 10b5-1 plan; `rule10b5_1: exclude` leaves them out of a sell screen.
- **Research data sets:** a company's whole Form 4 history since 2003, one row per line, with codes, prices, footnotes and holdings.
- **AI agents and spreadsheets:** `outputProfile: compact` gives one flat row per line, lists joined into text, and `summaryText` gives one plain sentence per row.

### What you get

Every row has a `type`: `transaction` (one line of a Form 4 or 5 transaction table, the paid row), `holding` (one holding line, paid, only for a Form 3 or when you ask for holding rows), `status` (free, one per kind of miss or input problem), `issuer_summary` and `cluster_buy` (free, at the end of the run when asked) and `summary` (free, the last row of every run).

#### Transaction row

One row per line, 78 fields. The blocks:

- **Filing:** `type`, `accessionNumber`, `form` (`4`, `4/A`, `5`, `5/A`), `isAmendment`, `dateOfOriginalSubmission`, `filedAt`, `acceptedAt`, `periodOfReport`, `schemaVersion`, `notSubjectToSection16`.
- **Company:** `issuerCik`, `issuerName`, `issuerTicker` (as filed, upper case, null for a placeholder such as NONE), `issuerTickerAsFiled`, `issuerCurrentTickers` and `issuerExchange` (from the SEC's list of listed tickers).
- **Insider:** `insiderCik`, `insiderName` (the SEC writes reporting owners last name first), `insiderRoles` (`Director`, `Officer`, `10% owner`, `Other`), `insiderTitle`, `insiderIsEntity`, `isDirector`, `isOfficer`, `isTenPercentOwner`, `isCeo`, `isCfo`, `isChair`, `insiderCount`, and `insiders`: every reporting owner of the filing (`cik`, `name`, `roles`, `officerTitle`, `otherText`, `isDirector`, `isOfficer`, `isTenPercentOwner`, `isOther`, `isEntity`, `address`).
- **Line:** `table` (`non-derivative` or `derivative`), `lineNumber`, `securityTitle`, `transactionDate`, `deemedExecutionDate`, `transactionCode`, `transactionCodeLabel`, `transactionCodeDescription`, `transactionFormType`, `equitySwapInvolved`, `transactionTimeliness`, `acquiredDisposed` (`A` or `D`), `direction`, `shares`, `pricePerShare`, `transactionValue` (shares times price, to the cent), `transactionTotalValue`, `isOpenMarketPurchase`, `isOpenMarketSale`.
- **Holding:** `sharesOwnedBefore`, `sharesOwnedAfter`, `valueOwnedAfter`, `ownershipChangePercent`, `isNewPosition`, `directOrIndirect` (`D` or `I`), `natureOfOwnership`.
- **Derivative terms:** `conversionOrExercisePrice`, `exerciseDate`, `expirationDate`, `underlyingSecurityTitle`, `underlyingSecurityShares`, `underlyingSecurityValue`.
- **Plan and signals:** `rule10b5_1Checked`, `rule10b5_1Mentioned`, `isPlannedTrade`, `signalScore`, `signalDrivers`, `dataQualityFlags`, `summaryText`.
- **Notes:** `footnotes`, `footnoteIdsByField`, `holdings` (the filing's holding lines: `table`, `securityTitle`, `sharesOwned`, `valueOwned`, `directOrIndirect`, `natureOfOwnership`, the derivative terms and `footnotes`), `remarks`, `signatureDate`, and `signatureName` (the person who signed, often an attorney in fact).
- **Links and run:** `filingUrl` (the filing's index page), `xmlUrl` (the ownership XML), `searchedBy` (the mode and the target that found the filing), `scrapedAt`.

A `holding` row has 53 fields: the filing, company and insider blocks, the line's security, `sharesOwned`, `valueOwned`, ownership, derivative terms, footnotes, `dataQualityFlags` and the links.

#### Fill rates

Measured on three runs of this Actor on the platform (build 0.1.1, the same code as the current build), 2026-11-02 UTC. **Market rows (1,275)**: run `4HwXwLgVv6czw1Lov`, `daysBack: 4`, every transaction line of the whole market filed 2026-10-29 and 2026-10-30 (576 filings, 288 companies; codes S 463, A 325, M 210, P 111, F 83 and others; 982 common stock lines and 293 derivative lines). **Purchase rows (300)**: run `YgV3MOZOV7EJrFKGp`, `transactionCodes: ["P"]` over 20 days back, 300 purchase lines from 171 filings filed 2026-10-26 to 2026-10-30 (113 companies; 279 common stock and 21 derivative lines). **Company rows (1,500)**: run `1llx6WTTL8DiEHcmP`, 20 large companies by ticker, 1,500 lines from 604 filings filed 2026-06-23 to 2026-10-30. A field counts as filled when it is not null, not an empty text and not an empty list.

| Field | What it holds | Market rows (1,275) | Purchase rows (300) | Company rows (1,500) |
|---|---|---|---|---|
| `accessionNumber`, `filedAt`, `periodOfReport`, `issuerCik`, `issuerName`, `insiderCik`, `insiderName`, `insiderRoles`, `transactionDate`, `transactionCode`, `acquiredDisposed`, `directOrIndirect`, `securityTitle`, `signalScore`, `summaryText`, `filingUrl`, `xmlUrl` | Identity, parties, line, links | 100% | 100% | 100% |
| `shares` | Shares or units of the line | 99.8% | 99.3% | 100% |
| `pricePerShare` | Price per share as filed | 93.7% | 99.3% | 97.5% |
| `transactionValue` | Shares times price | 93.6% | 98.7% | 97.5% |
| `sharesOwnedAfter` | Holding after the line | 99.8% | 98.7% | 100% |
| `sharesOwnedBefore` | Holding before, common stock lines | 99.7% (979 of 982) | 99.3% (277 of 279) | 100% (1,176 of 1,176) |
| `ownershipChangePercent` | Change in holding, common stock lines | 95.6% (939 of 982) | 86.0% (240 of 279) | 98.6% (1,160 of 1,176) |
| `issuerTicker` | Ticker as filed | 99.5% | 95.7% | 100% |
| `issuerExchange` | Exchange of a listed company | 99.5% | 95.3% | 100% |
| `insiderTitle` | Officer title or other relationship | 64.0% | 33.3% | 79.0% |
| `footnotes` (not empty) | Notes of the line, with text | 84.2% | 79.7% | 85.8% |
| `natureOfOwnership` | How an indirect holding is held | 23.1% | 55.3% | 12.5% |
| `deemedExecutionDate` | Deemed execution date | 0.7% | 1.7% | 0% |
| `conversionOrExercisePrice` | Exercise price, derivative lines | 61.8% (181 of 293) | 66.7% (14 of 21) | 42.0% (136 of 324) |
| `exerciseDate` | Date exercisable, derivative lines | 25.9% | 52.4% | 35.2% |
| `expirationDate` | Expiration date, derivative lines | 51.2% | 57.1% | 42.6% |
| `underlyingSecurityShares` | Underlying shares, derivative lines | 96.9% | 66.7% | 100% |
| `rule10b5_1Checked` (not null) | The Rule 10b5-1 checkbox | 100% | 100% | 100% |
| `isPlannedTrade` (true) | Planned trade (box or mention) | 25.5% | 8.3% | 32.0% |
| `remarks` | Remarks of the filing | 12.8% | 11.7% | 7.7% |
| `holdings` (not empty) | Holding lines attached | 31.5% | 31.7% | 48.9% |
| `acceptedAt` | Exact acceptance time | 0% (on only when asked) | 0% | 0% |

The rates follow the mix of lines: a grant (code A) is often reported at a price of 0 or with its price in a footnote only (all 80 market rows without a price carry `price_only_in_footnote`), most purchasers are directors, who have no officer title, and the Rule 10b5-1 checkbox exists only on filings from April 2023 on (null before). `acceptedAt` was filled on 400 of 400 rows with `includeAcceptanceTime` (run `bchrMFyixdgdZAzCV`) and on 30 of 30 rows read by accession number (run `mjpIbUYXURlQN57ye`), in US Eastern time with its offset, for example `2026-10-30T17:47:05-04:00`. `summaryText` is a sentence built only from the row's own fields, for example "Allison John W II (Director) sold 13,500 Common Stock of HOME BANCSHARES INC (HOMB) at USD 30.06, USD 405,783.00 in all on 2026-10-29."

Example Transaction row (real run `YgV3MOZOV7EJrFKGp` of 2026-11-02, build 0.1.1; shortened: 48 of its 78 fields, one of its two holding lines):

```json
{
  "type": "transaction",
  "accessionNumber": "0001534574-26-000018",
  "form": "4",
  "isAmendment": false,
  "filedAt": "2026-10-29",
  "acceptedAt": null,
  "periodOfReport": "2026-10-28",
  "issuerCik": "0000092230",
  "issuerName": "TRUIST FINANCIAL CORP",
  "issuerTicker": "TFC",
  "issuerCurrentTickers": ["TFC", "TFC-PI", "TFC-PO", "TFC-PR"],
  "issuerExchange": "NYSE",
  "insiderCik": "0001534574",
  "insiderName": "Lyons Michael P.",
  "insiderRoles": ["Director", "Officer"],
  "insiderTitle": "President & CEO",
  "isDirector": true,
  "isOfficer": true,
  "isCeo": true,
  "insiderCount": 1,
  "table": "non-derivative",
  "lineNumber": 1,
  "securityTitle": "Common Stock",
  "transactionDate": "2026-10-28",
  "transactionCode": "P",
  "transactionCodeLabel": "Purchase",
  "transactionCodeDescription": "Open market or private purchase of non-derivative or derivative security",
  "acquiredDisposed": "A",
  "direction": "acquired",
  "shares": 25000,
  "pricePerShare": 48.362,
  "transactionValue": 1209050,
  "sharesOwnedBefore": 21000,
  "sharesOwnedAfter": 46000,
  "ownershipChangePercent": 119.05,
  "isNewPosition": false,
  "directOrIndirect": "D",
  "isOpenMarketPurchase": true,
  "rule10b5_1Checked": false,
  "isPlannedTrade": false,
  "signalScore": 90,
  "signalDrivers": [
    "+50 open market or private purchase",
    "+15 chief executive or chief financial officer",
    "+15 value of USD 1,000,000 or more",
    "+10 holding changed by 25% or more"
  ],
  "footnotes": [
    {"id": "F1", "text": "The price in Column 4 is a weighted average price. The prices actually paid ranged from $48.3500 to $48.3800. The reporting person will provide to the issuer, any security holder of the issuer, or the SEC staff, upon request, information regarding the number of shares purchased at each price within the range."}
  ],
  "footnoteIdsByField": {"pricePerShare": ["F1"]},
  "holdings": [
    {"table": "derivative", "securityTitle": "Restricted Stock Units", "sharesOwned": 84951, "valueOwned": null, "directOrIndirect": "D", "natureOfOwnership": null, "conversionOrExercisePrice": null, "exerciseDate": null, "expirationDate": null, "underlyingSecurityTitle": "Common Stock", "underlyingSecurityShares": 84951, "footnotes": [{"id": "F2", "text": "On September 1, 2026, the reporting person was granted 84,951 restricted stock units, vesting in one-third increments on March 15, 2028, March 15, 2029, and March 15, 2030. Each restricted stock unit represents a right to receive one share of TFC common stock."}]}
  ],
  "filingUrl": "https://www.sec.gov/Archives/edgar/data/1534574/000153457426000018/0001534574-26-000018-index.htm",
  "xmlUrl": "https://www.sec.gov/Archives/edgar/data/1534574/000153457426000018/f4_a1eus00000anuuzmad-live.xml",
  "scrapedAt": "2026-11-02T05:45:42.507Z"
}
```

#### Signal score and flags

Every transaction row is scored by fixed rules, the same on every run, from the row's own fields. `signalScore` (0 to 100) adds: code P 50, code S 25, an exercise or conversion (X, O, C, M) 10, any other code 5; a chief executive or chief financial officer (the title holds CEO, Chief Executive, CFO or Chief Financial) 15, else an officer 10, a director 8, a 10% owner 5; a value of USD 1,000,000 or more 15, of USD 100,000 or more 10, of USD 10,000 or more 5; a new position 10, else a change in holding of 25% or more 10, of 10% or more 5; and takes 15 off for a planned trade. `signalDrivers` lists every step with its points. The score ranks rows; it is not advice.

`dataQualityFlags` names what the filing leaves unknown or marks as unusual: `price_only_in_footnote`, `no_price`, `no_shares`, `value_unknown`, `ticker_missing`, `ticker_placeholder`, `ticker_lower_case_as_filed`, `several_tickers_as_filed`, `late_filing`, `early_voluntary_report`, `amendment`, `not_subject_to_section_16`, `transaction_dated_after_filing`, `joint_filing`, `value_over_usd_1_billion` (a line worth a billion dollars or more, kept as filed: often a price typed in another unit) and `acceptance_time_not_read`.

`insiderIsEntity` is true when every reporting owner's name holds a company or fund word as a whole word: LLC, LP, LLP, Inc, Corp, Company, Ltd, Limited, Trust, Trustee, Fund, Partners, Partnership, Holding, Holdings, Capital, Management, Group, PLC, GmbH, AG, SA, NV, BV, Advisors, Advisers, Investment, Investments, Ventures, Foundation, Associates, Bank, Securities, Equity, Opportunities, Master, Offshore, Onshore. A name without one of these words is not called a person.

### How much does it cost to scrape SEC Form 4 insider trades?

You pay per row delivered plus a small start fee per run. Company summaries, cluster buys, status rows and the run summary are free.

| Event | FREE | BRONZE | SILVER | GOLD |
|---|---|---|---|---|
| Insider transaction (one line of a Form 4 or 5 transaction table, as a row) | $0.40 / 1,000 | $0.40 / 1,000 | $0.39 / 1,000 | $0.38 / 1,000 |
| Insider holding (a Form 3 position, or a holding line when you ask for holding rows) | $0.40 / 1,000 | $0.40 / 1,000 | $0.39 / 1,000 | $0.38 / 1,000 |
| Actor start (once per run) | $0.003 | $0.003 | $0.003 | $0.003 |

Platinum and Diamond plans pay the Gold price. The Actor start event is a flat fee with no tier discount, charged once when a run starts, whatever the run delivers.

The Store pricing card shows these same prices per 1,000 events: "$0.40 / 1,000" on the Insider transaction row means one row costs four hundredths of a cent.

Worked examples (start fee included):

| Run | FREE | BRONZE | SILVER | GOLD |
|---|---|---|---|---|
| A run that finds nothing | $0.003 | $0.003 | $0.003 | $0.003 |
| 20 rows (the prefill) | $0.011 | $0.011 | $0.0108 | $0.0106 |
| 100 rows | $0.043 | $0.043 | $0.042 | $0.041 |
| 1,000 rows | $0.403 | $0.403 | $0.393 | $0.383 |
| 10,000 rows | $4.003 | $4.003 | $3.903 | $3.803 |

What is free (only the run's start fee is charged for it): an invalid input, an unknown ticker, CIK or name, an ambiguous company name, a filing that is not found or is not a Form 3, 4 or 5, a filing or a line your filters leave out, a line already delivered in the run, a read that failed, the holding lines attached to a transaction row, every status row, every company summary and cluster buy row, and the run summary. Rows are charged only after they are in your dataset, and your maximum charge per run is respected: a row that does not fit is not delivered, a free `filing_cut` row says how many lines were delivered when only part of a filing fitted, and the summary says `stoppedBy: charge_limit`. A platform restart never charges a row twice (the platform itself charges the start fee once more when a run is resurrected).

### Input

Every field is optional. Which targets are present decides the kind of run (see Modes below); when any target field is present, even empty, the run reads those targets and is never widened into the whole market (an empty list is a free `invalid_input` row). An input field this Actor does not know stops the run with a free row, because it could be a filter under another name.

#### Whose insider trades

| Field | Default | What it does |
|---|---|---|
| `tickers` | empty (prefill `AAPL`, `NVDA`, `TSLA`) | Stock tickers such as `AAPL` or `BRK-B` (`BRK.B` is read as `BRK-B`), matched through the SEC's list of listed tickers. |
| `issuerCiks` | empty | Company CIKs, with or without leading zeros, or an EDGAR company link. Use a CIK for a company without a ticker. |
| `companyNames` | empty | Names of listed companies, for example `Apple Inc.`; used only when exactly one listed company carries the name (letters and digits compared). |
| `insiderCiks` | empty | CIKs of reporting owners (officers, directors, 10% owners, funds) or their EDGAR links: every line they reported, at every company. |
| `insiderNames` | empty | Names as the SEC writes reporting owners, last name first, for example `Musk Elon`; a row is kept when one reporting owner's name holds every word (1 to 6 words). |
| `accessionNumbers` | empty | Form 3, 4 or 5 filings by accession number (`0001104659-26-075213`) or EDGAR filing link, read as asked. Cannot be combined with companies or insiders. |

#### Filing dates and forms

| Field | Default | What it does |
|---|---|---|
| `daysBack` | empty | Filings filed in the last N days, 0 to 9,000 (0 is today only, by the SEC's US Eastern date). Cannot be combined with `dateFrom`. |
| `dateFrom`, `dateTo` | empty | First and last filing date, `YYYY-MM-DD`. Without a window, a market run reads today and the 6 days before and a company or insider run reads back to 2003-06-30. |
| `maxAgeHours` | empty | Only filings the SEC accepted in the last N hours (1 to 17,520), by their exact acceptance time; one more request per filing with matching lines. Cannot be combined with the dates. |
| `formTypes` | `4` | `4` (a change in ownership), `5` (the annual statement), `3` (the first statement of holdings, holding rows only). |
| `includeAmendments` | `true` | Read 4/A, 5/A and 3/A too; an amendment row carries `isAmendment` and `dateOfOriginalSubmission`. |

#### Which trades

| Field | Default | What it does |
|---|---|---|
| `preset` | none | A ready-made filter set that fills only the filters you leave empty: `open_market_buys` (code P, common stock lines), `open_market_sales` (code S, common stock lines), `officer_trades` (P and S by officers), `planned_sales` (S under a Rule 10b5-1 plan), `large_trades` (P and S of USD 1,000,000 or more), `ten_percent_owner_trades` (P and S by 10% owners). |
| `transactionCodes` | every code | Any of the 20 SEC codes: P, S, A, M, F, G, D, C, X, O, J, I, L, W, Z, K, E, H, U, V. |
| `acquiredDisposed` | both | `A` (acquired) or `D` (disposed). |
| `minTransactionValue`, `maxTransactionValue` | none | Lines worth at least or at most this many US dollars; a line without a known value is left out by these filters. |
| `minShares` | none | Lines of at least this many shares. |
| `transactionDateFrom`, `transactionDateTo` | none | Lines traded on or after, on or before these days (the filing date window still decides which filings are read). |
| `securityTables` | both | `non-derivative` (shares) or `derivative` (options, units, warrants). |
| `insiderRoles` | every role | `director`, `officer`, `ten_percent_owner`, `other`. |
| `officerTitleContains` | empty | An insider's officer title holds every word, for example `CEO` or `Chief Financial Officer`. |
| `rule10b5_1` | `any` | `only` planned trades or `exclude` them. |
| `excludeEntityInsiders` | `false` | Leave out filings whose every reporting owner is a fund, trust or company (the word list above). |
| `footnoteTextContains` | empty | Lines whose footnotes or the filing's remarks contain this text (any case), for example `weighted average` or `gift`. |

#### Output

| Field | Default | What it does |
|---|---|---|
| `includeHoldingRows` | `false` | Holding lines of Forms 4 and 5 as rows of their own, charged as Insider holding. Off: they ride free on every transaction row as `holdings`. Form 3 lines are always holding rows. |
| `includeAcceptanceTime` | `false` | Reads each delivered filing's header page for `acceptedAt`: one more request per filing with rows, no extra charge. |
| `includeIssuerSummaries` | `false` | One free `issuer_summary` row per company at the end of the run. |
| `detectClusterBuys` | `false` | Free `cluster_buy` rows at the end of the run. |
| `clusterMinInsiders` | 3 | Different insiders a cluster needs, 2 to 50. |
| `clusterWindowDays` | 14 | Days a cluster may span by transaction date, 1 to 365. |
| `clusterIncludeEntities` | `true` | Count funds and companies as insiders of a cluster. |
| `sortBy` | none | Also save every delivered row in this order to the record `SORTED-ROWS`: `filingDate`, `transactionDate`, `value`, `shares`, `ticker`, `signalScore`. |
| `sortOrder` | `desc` | `desc` (highest or newest first) or `asc`. |
| `outputProfile` | `full` | `full` (nested lists) or `compact` (one flat row per line: `footnotesText`, `insiderNames`, `insiderAddress` and lists joined into text; `insiders`, `holdings` and `footnoteIdsByField` left out). |
| `includePersonalData` | `false` | No effect: all public data is always delivered (kept so saved inputs keep working). |

#### Limits

| Field | Default | What it does |
|---|---|---|
| `maxItems` | 100 (prefill 20) | The most transaction and holding rows this run delivers and charges, 1 to 100,000. |
| `maxFilingsPerCompany` | none | At most this many filings with delivered rows per company, newest first; the run goes on for the others. |
| `maxRowsPerCompany` | none | At most this many rows per company. |
| `maxFilingsRead` | none | Stop after reading this many filings, whatever they matched (for example the latest 500 Form 4s of the market). |
| `maxRunSeconds` | none | Stop reading after this many seconds (30 to 86,400) and finish with what was delivered. |
| `maxRequestsPerSecond` | 4 | Pace of requests to the SEC, 1 to 4. |
| `proxyConfiguration` | off | Not needed. With Apify Proxy on, every request goes through one Apify datacenter proxy session. Own proxy URLs are not used (a free `invalid_input` row). |

Personal data: every public field of the filing is delivered on every run: insider names, CIKs, roles and titles, each insider's mailing address as filed (`street1`, `street2`, `city`, `state`, `zipCode`, `stateDescription` in `insiders[].address`, `insiderAddress` in compact rows) and the signer's name (`signatureName`). `includePersonalData` has no effect; it is kept so saved inputs keep working. You are responsible for a lawful use of personal data (GDPR included).

### Modes

- **Market** (no target field): every Form 4 (or the forms you choose) filed in the window, newest first. The default window is today and the 6 days before, US Eastern.
- **Companies** (`tickers`, `issuerCiks`, `companyNames`): the filings whose issuer is one of the companies, searched 100 companies at a time, back to 2003-06-30 by default. A filing where one of the companies is only a reporting owner of another company's shares is left out and counted in the summary.
- **Insiders** (`insiderCiks`, `insiderNames`): the filings where a reporting owner is one of the insiders, at every company; with companies given too, only their trades in those companies.
- **Accession numbers** (`accessionNumbers`): each filing as asked, with its filing date and acceptance time from the filing's header page. The row filters apply; the date window and form settings do not.

All searches of a run are merged newest first (filing date), so `maxItems` takes the newest filings of every company or insider alike. A filing whose lines pass `maxItems` or the charge limit is cut after its first lines in the filing's order, with a free `filing_cut` row.

### Filters

Form filters (`formTypes`, `includeAmendments`) act before a filing is read. Every other filter is judged on each parsed line, never guessed: a value or share filter passes only a line whose number the filing gives. The role, title and entity filters keep a filing when a reporting owner matches; a holding row is left out whenever a filter that only a transaction can meet (codes, A or D, value, shares, trade dates, Rule 10b5-1) is set. A preset fills only the filters you leave empty; a filter you set is used as you set it.

### End of run rows

- **Company summaries** (`includeIssuerSummaries`): one free `issuer_summary` row per company over the rows this run delivered: `issuerCik`, `issuerName`, `issuerTicker`, `transactions`, `insiders`, `purchases` and `sales` (`count`, `shares`, `value`, `valueUnknown`), `netOpenMarketValue`, `otherTransactions`, `firstTransactionDate`, `lastTransactionDate`, `topInsiders` (up to 5, with `purchaseValue` and `saleValue`).
- **Cluster buys** (`detectClusterBuys`): one free `cluster_buy` row per cluster of purchases (code P) by at least `clusterMinInsiders` different insiders of one company within `clusterWindowDays` by transaction date; clusters never overlap. Fields: `issuerCik`, `issuerName`, `issuerTicker`, `firstTransactionDate`, `lastTransactionDate`, `insiders`, `insiderList`, `purchases`, `shares`, `value`, `purchasesWithUnknownValue`, `accessionNumbers`, `rule`. In run `YgV3MOZOV7EJrFKGp` (300 purchase rows, `clusterMinInsiders: 2`) the run found 14 clusters and wrote 113 company summaries, for example 6 directors and officers of Beacon Financial Corp buying 9,029 shares for USD 274,326.33 between 2026-10-26 and 2026-10-30.
- **Sorted list** (`sortBy`): the record `SORTED-ROWS` in the run's key-value store lists every delivered row (`type`, `accessionNumber`, `table`, `lineNumber`, `issuerCik`, `issuerName`, `issuerTicker`, `insiderCik`, `insiderName`, `transactionCode`, `acquiredDisposed`, `shares`, `pricePerShare`, `transactionValue`, `transactionDate`, `filedAt`, `signalScore`, `isOfficer`, `isDirector`, `insiderIsEntity`) in the order asked; rows without the sort value come last. The dataset keeps the reading order, newest filing first.

At most 1,000 summary and cluster rows are written per run. They cover the rows this run delivered, not the whole market.

#### Status rows and the summary row (free)

Every input problem and every miss gets a free `type: "status"` row with `scope`, `status` and a `message` in plain words; misses of one kind share one row with their `items` and `count`. Status values: `invalid_input`, `unusable_item`, `unknown_ticker`, `company_name_not_found`, `name_ambiguous_or_inexact` (with up to 10 near `candidates`; nothing is guessed), `same_company_twice`, `no_filings_in_window`, `insider_name_not_found`, `insider_name_no_owner_match`, `accession_not_found`, `accession_not_found_or_agent_filed`, `accession_not_an_insider_filing`, `accession_without_ownership_xml`, `xml_not_served`, `nothing_to_read`, `filing_cut` and `note`.

The last row of every run is a free `type: "summary"` row: `status` (`complete`, `partial` or `invalid_input`), `mode`, `stoppedBy` (for example `max_items`, `charge_limit`, `work_allowance`, `max_filings_read`, `max_run_seconds`, `source_unavailable`), `rowsDelivered`, `window`, `preset`, `chargedEvents`, `counts` (filings listed and read, lines filtered out and more), `coverage` (per company, insider, search or filing), `sorted`, `sourceFailures`, `requests`, `allowance`, `resumed` and `message`.

### What this Actor does NOT do

- No monitor, no alerts and no memory between runs: each run reads what its input asks. For a feed, schedule it with `maxAgeHours` or `daysBack`; a filing inside two runs' windows is delivered and charged by both.
- No e-mail address in its requests and no User-Agent setting: the User-Agent names Automation Craft and its Store page.
- No fuzzy name guessing: a company name is used only when exactly one listed company carries it (otherwise a free row lists candidates), and an insider name only when one reporting owner's name holds every word.
- No company lookup by web domain (apple.com): the SEC's filer records carry no usable website; give the ticker, CIK or listed name.
- No other SEC forms in this Actor: no 13F holdings, 8-K, 10-K, Schedule 13D or 13G, Form 144 or Form D rows. Forms 3, 4 and 5 only.
- No data from third party insider websites: every row comes from the SEC's own filings.
- No investment advice: `signalScore` is the fixed formula above, and `summaryText` is one sentence built from the row's own fields, with no AI.
- No market prices: `pricePerShare` is the price the insider filed, not a quote.
- No filings before 2003-06-30: they were filed on paper or as text, not XML; a window that reaches back further says so in a free note.
- No acceptance time unless asked: `acceptedAt` is on rows read by accession number, with `includeAcceptanceTime` or with `maxAgeHours`.
- No free first rows: every row is charged from the first one.
- No own proxy URLs: `proxyUrls` in `proxyConfiguration` stops the run with a free row.

### Limits and honest notes

- **Pace and speed.** At most 4 requests per second to the SEC, one per filing read (plus one per filing with rows when the acceptance time is read). Measured on the platform at 256 MB, 2026-11-02: the prefill, 20 rows, 4 seconds (run `9FbKeM22yv92wEyGM`); the newest 100 rows of the market, 19 seconds (`ksRgqRU3EAG1X8gsW`); 600 rows of the market, 171 seconds with one platform restart in the middle (`qfypQ6ze5I0GBz0f5`); 1,500 rows of 20 large companies, 323 seconds (`1llx6WTTL8DiEHcmP`); 30 purchases of USD 10,000 or more from 395 filings read, 113 seconds (`6sieaJVocyEeOicvl`); 300 purchases from 1,428 filings read, 408 seconds (`YgV3MOZOV7EJrFKGp`); 400 rows with the acceptance time, 144 seconds (`bchrMFyixdgdZAzCV`). A narrow filter over the whole market reads many filings per row it keeps, so it takes longer than its row count suggests.
- **The free work allowance.** Reading a filing whose lines no filter keeps earns nothing, so a run reads about 100 such filings on its own budget, and every row it delivers earns it room for about 20 more. When the room is used up the run stops starting new reads, delivers what it has and ends with `stoppedBy: work_allowance` and a message that says so; only the run's start fee and the rows delivered are charged. Measured: transaction code W (will or inheritance) over 30 days of the whole market read 100 filings, found none and stopped this way in 32 seconds (run `vOnoJLVVn2Zot0gAN`). For a rare code or a narrow filter, give companies or insiders, or a shorter window.
- **How far back.** Insider filings are XML from 2003-06-30. A company or insider run reads back to that date unless you set a window.
- **Late filings.** Filings are listed by their filing date, also with `maxAgeHours` (its window starts on the day of its cutoff). A filing can be accepted days after the filing date it carries, so a schedule that reads only the last day can miss it; a schedule with a few days of overlap (for example `daysBack: 3` every day) finds it, and delivers and charges the overlap again.
- **Values.** `transactionValue` is `shares` times `pricePerShare` as filed. On derivative lines both numbers are the derivative's own (units and their price), so a value there is not a value in common stock; sort and filter by value with that in mind, or set `securityTables` to `non-derivative`. Values are never corrected: a filing with a mistyped price gives a wrong value (in run `YgV3MOZOV7EJrFKGp` one filing's price of USD 3,149.47 per share gave two lines worth USD 9.9 billion and USD 17.3 billion), so a line worth USD 1 billion or more carries the flag `value_over_usd_1_billion`; check it against `xmlUrl` before you rely on it.
- **Per run:** up to 500 tickers, CIKs, names and accession numbers together and 50 values per filter list.
- **Source failures.** Requests go out from the run's own address; if the SEC refuses it three times in a row, the rest of the run goes through one Apify datacenter proxy session at the same pace. If the SEC refuses that too, the run stops with `stoppedBy: source_unavailable` and nothing more is charged.

### About the data

The data is the SEC's public insider filing data as filed, read from EDGAR with a declared User-Agent. The SEC's website policy says its information may be copied or further distributed by users of the website without the SEC's permission. Footnotes and remarks are the filer's own text. This Actor is an independent tool. It is not affiliated with or approved by the U.S. Securities and Exchange Commission (SEC).

### API examples

Every run is also an insider trading API call over the Apify API: send the input, read the rows.

curl (synchronous run, returns the rows):

```bash
curl -X POST "https://api.apify.com/v2/acts/automation_craft~sec-form-4-insider-trading-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"preset":"open_market_buys","minTransactionValue":100000,"daysBack":3,"maxItems":50}'
```

Node.js with `apify-client`:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation_craft/sec-form-4-insider-trading-scraper').call({
    insiderCiks: ['1494730'],
    transactionCodes: ['S'],
    maxItems: 200,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const row of items) if (row.type === 'transaction') console.log(row.issuerTicker, row.transactionDate, row.shares, row.pricePerShare, row.isPlannedTrade);
```

Python with `apify-client`:

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("automation_craft/sec-form-4-insider-trading-scraper").call(
    run_input={"tickers": ["AAPL", "NVDA", "TSLA"], "daysBack": 90, "maxItems": 1000, "includeIssuerSummaries": True}
)
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row["type"] == "issuer_summary":
        print(row["issuerTicker"], row["purchases"]["value"], row["sales"]["value"], row["netOpenMarketValue"])
```

### FAQ

#### Is there an API to pull insider trading data?

Yes. Every run of this Actor is an API call: send the input to the Apify API and read one row per transaction line as JSON (curl, Node.js and Python examples above). It reads the SEC's own Form 4 XML, so no SEC key or account is needed, only your Apify token.

#### How do I read an SEC Form 4 filing?

Each row is one line of the filing's table. `transactionCode` says what happened (P open market purchase, S sale, A grant, M exercise, F shares withheld for taxes, G gift) and `transactionCodeLabel` spells it out; `acquiredDisposed` is A or D; `shares`, `pricePerShare` and `sharesOwnedAfter` are as filed; `directOrIndirect` is D or I; `footnotes` holds the notes the line points to, with their text.

#### Can I get new Form 4 filings as soon as they are filed?

This Actor sends no alerts: each run reads what its input asks. Schedule it on Apify (for example every hour) with `maxAgeHours` to get the filings the SEC accepted in the last N hours by their exact acceptance time. A filing inside two runs' windows is delivered and charged by both.

#### How much does SEC Form 4 data cost?

The SEC publishes the filings for free. This Actor charges USD 0.40 per 1,000 rows on the Free plan (USD 0.38 on Gold) plus USD 0.003 per run. Misses, status rows, company summaries, cluster buys and lines your filters leave out are free.

#### Why does this Actor run with limited permissions?

It runs with Apify's limited permissions, the least privilege level: it reads its input and writes only its own run's dataset and key-value store, and it reads its dataset back after a platform restart so no row is charged twice. It opens no named store and touches nothing else in your account.

### Changelog

- 0.1 (November 2026): first release. Forms 3, 4 and 5 from 2003-06-30; market, company, insider and accession number modes; one row per line with 78 fields; free company summaries, cluster buys and the `SORTED-ROWS` record.

### More data tools by Automation Craft

- [SEC Filings Scraper: 10-K, 8-K, Full-Text Search](https://apify.com/automation_craft/sec-filings-scraper)
- [SEC Form D Scraper: Offerings & Funding Leads](https://apify.com/automation_craft/sec-form-d-scraper)
- [Yahoo Finance Scraper: Quotes, History, Financials](https://apify.com/automation_craft/yahoo-finance-scraper)
- [LinkedIn Company Employees Scraper - No Login](https://apify.com/automation_craft/linkedin-company-employees-scraper)
- [Meta Ads Library Scraper - Meta Ad Library API](https://apify.com/automation_craft/meta-ads-library-scraper)
- [Google Trends API & Scraper: Trending Searches](https://apify.com/automation_craft/google-trends-scraper)

# Changelog

This Actor's version history is a separate document: https://apify.com/automation_craft/sec-form-4-insider-trading-scraper/changelog.md

# Actor input Schema

## `tickers` (type: `array`):

Stock ticker symbols of listed companies, for example AAPL, TSLA or BRK-B (BRK.B is read as BRK-B). Each is matched to its company through the SEC's list of listed tickers; a ticker the SEC does not list gets a free status row. Rows are the insider trades in these companies' shares.

## `issuerCiks` (type: `array`):

SEC Central Index Keys (CIK) of the companies whose insiders you want, with or without leading zeros (320193 or 0000320193), or an EDGAR company link. Use a CIK for a company that has no ticker.

## `companyNames` (type: `array`):

Names of listed companies, for example Apple Inc. A name is used only when exactly one listed company carries it (letters and digits compared; case, punctuation and spacing aside). Otherwise a free status row lists the nearest listed names. Given as one text instead of a list, put one name per line.

## `insiderCiks` (type: `array`):

CIKs of reporting owners (the insiders: officers, directors, 10% owners, funds), or their EDGAR links. Rows are every trade they reported, at every company. With companies given too, only their trades in those companies.

## `insiderNames` (type: `array`):

Names of insiders as the SEC writes reporting owners, last name first, for example Musk Elon or Huang Jen Hsun. A row is kept when one reporting owner's name holds every word (whole words, any case). With companies given too, only their trades in those companies. Given as one text, put one name per line.

## `accessionNumbers` (type: `array`):

Form 3, 4 or 5 filings to read as asked, by accession number (0001104659-26-075213) or EDGAR filing link. A bare accession number is looked up under the CIK its first ten digits name; for a filing an agent filed, paste its EDGAR link. The row filters below apply; the filing date window and form settings do not. Cannot be combined with companies or insiders.

## `daysBack` (type: `integer`):

Read filings filed in the last N days (0 = today only, by the SEC's US Eastern date). Cannot be combined with dateFrom.

## `dateFrom` (type: `string`):

First filing date to read, YYYY-MM-DD. Insider filings are XML from 2003-06-30; older ones are counted, not delivered.

## `dateTo` (type: `string`):

Last filing date to read, YYYY-MM-DD (default: today).

## `maxAgeHours` (type: `integer`):

Only filings the SEC accepted in the last N hours, by their exact acceptance time (one more request per filing with matching lines; the acceptance time is then on every row). Filings are found by filing date from the day the window starts, so a filing the SEC dates earlier than that day is not read. Cannot be combined with dateFrom, dateTo or daysBack.

## `formTypes` (type: `array`):

Which ownership forms to read. Form 4 (the default) reports a change within two business days; Form 5 is the annual statement of late or exempt trades; Form 3 is the first statement of holdings (holding rows only).

## `includeAmendments` (type: `boolean`):

Read amended filings too (on by default). An amendment row carries isAmendment and the date of the original filing.

## `preset` (type: `string`):

A ready made filter set. It fills only the filters you leave empty; a filter you set yourself is used as you set it. Open market buys: code P, shares. Open market sales: code S, shares. Officer trades: P and S by officers. Planned sales: S under a Rule 10b5-1 plan. Large trades: P and S of USD 1,000,000 or more. 10% owner trades: P and S by 10% owners.

## `transactionCodes` (type: `array`):

Only lines with these SEC transaction codes. P and S are open market purchases and sales; A grants; M exercises; F shares withheld for taxes; G gifts. Empty: every code.

## `acquiredDisposed` (type: `string`):

Only acquisitions (A) or only disposals (D). Empty: both.

## `minTransactionValue` (type: `number`):

Only lines worth at least this many US dollars (shares times price per share). A line whose price the filing gives only in a footnote, or not at all, has no known value and is left out by this filter.

## `maxTransactionValue` (type: `number`):

Only lines worth at most this many US dollars. Lines without a known value are left out by this filter.

## `minShares` (type: `number`):

Only lines of at least this many shares.

## `transactionDateFrom` (type: `string`):

Only lines with a transaction date on or after this day, YYYY-MM-DD (the filing date window still decides which filings are read).

## `transactionDateTo` (type: `string`):

Only lines with a transaction date on or before this day, YYYY-MM-DD.

## `securityTables` (type: `array`):

Common stock lines (non-derivative table), options and other derivative lines (derivative table), or both (default).

## `insiderRoles` (type: `array`):

Only filings where a reporting owner holds one of these roles. Empty: every role.

## `officerTitleContains` (type: `string`):

Only filings where an insider's officer title holds every word of this text (whole words, any case), for example CEO, Chief Financial Officer or President.

## `rule10b5_1` (type: `string`):

Keep every line (any), only planned trades (only), or leave planned trades out (exclude). A trade counts as planned when the filing ticks the Rule 10b5-1 box (Forms filed from April 2023) or its footnotes or remarks name Rule 10b5-1.

## `excludeEntityInsiders` (type: `boolean`):

Leave out filings whose every reporting owner is a fund, trust or company (a name with a word such as LLC, LP, Inc, Trust, Fund, Partners, Capital or Holdings).

## `footnoteTextContains` (type: `string`):

Only lines whose footnotes or the filing's remarks contain this text (any case), for example 10b5-1, gift, trust or weighted average.

## `includeHoldingRows` (type: `boolean`):

Deliver the holding lines of Forms 4 and 5 (positions reported without a trade) as rows of their own, charged as Insider holding. Off by default: they are attached to every transaction row as holdings, free. Form 3 lines are always holding rows.

## `includeAcceptanceTime` (type: `boolean`):

Read each delivered filing's header page for the exact time the SEC accepted it (acceptedAt, US Eastern with offset). One more request per filing with rows, no extra charge.

## `includeIssuerSummaries` (type: `boolean`):

At the end of the run, one free row per company: transactions, insiders, open market buys and sells (count, shares, dollars), net buying and the top insiders, over the rows this run delivered.

## `detectClusterBuys` (type: `boolean`):

At the end of the run, one free row per cluster: open market purchases (code P) by several different insiders of one company within a few days, over the rows this run delivered.

## `clusterMinInsiders` (type: `integer`):

Different insiders a cluster needs (default 3). Only with detectClusterBuys.

## `clusterWindowDays` (type: `integer`):

Days a cluster may span, by transaction date (default 14). Only with detectClusterBuys.

## `clusterIncludeEntities` (type: `boolean`):

Count insiders whose name is a fund, trust or company toward a cluster (on by default). Only with detectClusterBuys.

## `sortBy` (type: `string`):

Also save every delivered row in this order to the run's key-value store (record SORTED-ROWS): filing date, transaction date, value, shares, ticker or signal score. The dataset keeps the reading order (newest filing first).

## `sortOrder` (type: `string`):

Highest first (desc, default) or lowest first (asc). Only with sortBy.

## `outputProfile` (type: `string`):

full (default): nested lists of insiders, footnotes and holdings. compact: one flat row per line for spreadsheets and AI agents (lists joined into text).

## `includePersonalData` (type: `boolean`):

All public data is always delivered, so this setting has no effect (it is kept so saved inputs keep working).

## `maxItems` (type: `integer`):

The run stops after this many transaction and holding rows (default 100). Status, summary and company rows are free and not counted.

## `maxFilingsPerCompany` (type: `integer`):

At most this many filings with delivered rows per company (newest first); the run goes on for the other companies.

## `maxRowsPerCompany` (type: `integer`):

At most this many rows per company; the run goes on for the other companies.

## `maxFilingsRead` (type: `integer`):

Stop after reading this many filings, whatever they matched (for example the latest 500 Form 4s of the market).

## `maxRunSeconds` (type: `integer`):

Stop reading after this many seconds and finish with what was delivered.

## `maxRequestsPerSecond` (type: `integer`):

Pace of requests to the SEC, 1 to 4 per second (default 4, under the SEC's fair access limit of 10).

## `proxyConfiguration` (type: `object`):

Not needed: the SEC answers the run's own address, and one Apify datacenter proxy session is the single fallback when it refuses. Turn on Apify Proxy to send every request through that session.

## Actor input object example

```json
{
  "tickers": [
    "AAPL",
    "NVDA",
    "TSLA"
  ],
  "maxItems": 20
}
```

# Actor output Schema

## `items` (type: `string`):

No description

## `sortedRows` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "tickers": [
        "AAPL",
        "NVDA",
        "TSLA"
    ],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation_craft/sec-form-4-insider-trading-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "tickers": [
        "AAPL",
        "NVDA",
        "TSLA",
    ],
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation_craft/sec-form-4-insider-trading-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "tickers": [
    "AAPL",
    "NVDA",
    "TSLA"
  ],
  "maxItems": 20
}' |
apify call automation_craft/sec-form-4-insider-trading-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation_craft/sec-form-4-insider-trading-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/r2ZCB1BTh0ObKTMh5/builds/FzbWV6e4Q7IGSUoe8/openapi.json
