# Form 4 Insider Trades Watch: Buys & Sells (`glaciological_huddle/form4-insider-watch`) Actor

Daily insider buys and sells from public Form 4 filings: one flat row per transaction with insider, role, shares, price, value and 10b5-1 flag. New-only mode.

- **URL**: https://apify.com/glaciological_huddle/form4-insider-watch.md
- **Developed by:** [Clark Scroggin](https://apify.com/glaciological_huddle) (community)
- **Categories:** Business, Automation, News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 insider transaction rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Form 4 Insider Trades Watch: Buys & Sells

> **Unofficial; not affiliated with or endorsed by the U.S. Securities and Exchange Commission.** This Actor reads public Form 4 filings from the SEC's EDGAR archive (daily index files, each filing's folder listing and its Form 4 XML) with a declared User-Agent at a polite request rate. **Data only; not investment advice.**

**Insider buys and sells as flat rows.** When a director, officer or 10% owner of a US-listed company buys, sells, exercises options or receives a grant, they report it on a Form 4, due within two business days of the trade. Form 4 Insider Trades Watch turns each new filing into **one row per transaction**: company and ticker, insider name and role (director, officer with title, 10% owner), transaction date and code with its plain-English meaning, shares, price, **value (shares × price)**, shares owned afterwards, direct or indirect ownership, the footnotes for that transaction, whether the trade was made under a **Rule 10b5-1 plan**, and a link to the filing. Run it on a schedule with **Only new** on and every run outputs just the transactions you have not seen.

By default you get **open-market and private purchases and sales (codes P and S)**. Add any other codes (grants, option exercises, tax withholding, gifts...) and the derivative table (options, RSUs, warrants) when you need them.

### Who uses it

- **Investors and analysts** following insider buying at companies they own or watch, or screening the whole market for sizeable director and officer purchases.
- **Newsletter writers and researchers** who need a clean daily feed of insider activity by ticker, role and size.
- **Compliance and IR teams** keeping an eye on filings by their own insiders or a peer group.
- **Data teams** loading insider transactions into a warehouse, Sheets or a dashboard without parsing XML.

### What you get

One row per transaction, flat fields, CSV-friendly. Below is a real row from a test run (Apple Inc., Form 4 filed 2026-10-19; one of several sales the officer reported in the same filing):

```json
{
  "accessionNumber": "0001140361-26-040126",
  "rowIndex": 2,
  "formType": "4",
  "isAmendment": false,
  "dateOfOriginalSubmission": null,
  "filedDate": "2026-10-19",
  "periodOfReport": "2026-10-15",
  "issuerCik": "320193",
  "issuerName": "Apple Inc.",
  "ticker": "AAPL",
  "reportingOwnerCik": "2050912",
  "reportingOwnerName": "Parekh Kevan",
  "isDirector": false,
  "isOfficer": true,
  "officerTitle": "Senior Vice President, CFO",
  "isTenPercentOwner": false,
  "isOther": false,
  "otherRelationship": null,
  "securityTitle": "Common Stock",
  "transactionDate": "2026-10-16",
  "transactionCode": "S",
  "transactionCodeText": "Open-market or private sale",
  "acquiredDisposed": "D",
  "shares": 200,
  "pricePerShare": 342.66,
  "value": 68532,
  "sharesOwnedAfter": 18731,
  "directOrIndirect": "D",
  "natureOfOwnership": null,
  "isDerivative": false,
  "conversionOrExercisePrice": null,
  "exerciseDate": null,
  "expirationDate": null,
  "underlyingSecurityTitle": null,
  "underlyingShares": null,
  "footnotes": "F3: This transaction was made pursuant to a Rule 10b5-1 trading plan adopted by the reporting person on November 21, 2025. | F4: This transaction was executed in multiple trades at prices ranging from $342.25 to $342.88; the price reported above reflects the weighted average sale price. ...",
  "is10b5_1Plan": true,
  "filingIndexUrl": "https://www.sec.gov/Archives/edgar/data/320193/000114036126040126/0001140361-26-040126-index.htm",
  "xmlUrl": "https://www.sec.gov/Archives/edgar/data/320193/000114036126040126/form4.xml",
  "isNew": true,
  "fetchedAt": "2026-10-22T05:08:04.999Z",
  "source": "www.sec.gov Archives, Form 4 ownership XML (public filing data)"
}
```

(The footnote text is shortened here; the dataset holds it in full.)

Notes on the columns:

- `value` is `shares × pricePerShare` in US dollars, rounded to cents. It is `null` when the filing gives no price (some filers put the price only in a footnote). Grants and option exercises often carry a price of 0, so their value is 0.
- `transactionCode` is the Form 4 code (`P`, `S`, `A`, `M`, `F`, `G`...); `transactionCodeText` spells it out. `acquiredDisposed` is `A` or `D`.
- `footnotes` holds only the footnotes the transaction refers to, as `F1: ... | F2: ...`. Weighted-average price ranges, 10b5-1 plan dates and ownership explanations usually live here.
- `is10b5_1Plan` is `true` when the filing's Rule 10b5-1 checkbox (on the form since 2023) is ticked or one of the transaction's footnotes says the trade was under a 10b5-1 plan, `false` when the checkbox is present and unticked, `null` when the filing has neither.
- Joint filings (for example a fund and its manager) list several owners: `reportingOwnerName` and `reportingOwnerCik` join them with `; ` and a role flag is `true` when any of them has the role.
- Derivative rows (`isDerivative: true`, only with **Include derivative transactions**) add `conversionOrExercisePrice`, `exerciseDate`, `expirationDate`, `underlyingSecurityTitle` and `underlyingShares`.
- `accessionNumber` + `rowIndex` identify a row uniquely. Empty values are `null`, never empty strings.

A `RUN_SUMMARY` record in the run's key-value store has the counts: index days read and missing, Form 4 filings in the index, filings skipped by ticker before download, filings downloaded, rows filtered out by which filter, errors, requests used and why the run stopped.

### How to use it

1. **Pick companies, or the whole market.** Enter **Tickers** (AAPL, MSFT...) or **Issuer CIKs**. Only those companies' filings are downloaded, so watch runs are small and quick. Leave both empty to scan the whole market.
2. **Pick what counts.** Keep the default P and S codes for buys and sells, or choose others. Narrow by **Insider roles** and **Minimum transaction value**.
3. **Name the watch.** `watchName` is the memory key; use one per saved search. The first run of a new watch returns everything that matches in the window (up to **Max items**); from then on, only transactions not output before.
4. **Schedule it.** Add a daily schedule in Apify with `daysBack` 1. Each day's index file appears in the evening (US Eastern), so a morning run picks up the previous business day's filings.
5. **Connect the output.** Send the dataset to Google Sheets, Slack, email, webhooks, Zapier, Make, n8n or your own API with Apify integrations. Quiet runs push nothing.

#### Example 1: Buys and sells at big tech companies

```json
{
  "tickers": ["AAPL", "MSFT", "NVDA", "TSLA", "AMZN", "GOOGL", "META"],
  "daysBack": 1,
  "transactionCodes": ["P", "S"],
  "watchName": "big-tech",
  "maxItems": 200
}
```

#### Example 2: Whole market, director and officer purchases of $100,000 or more

```json
{
  "daysBack": 1,
  "transactionCodes": ["P"],
  "minTransactionValue": 100000,
  "insiderRoles": ["director", "officer"],
  "watchName": "insider-buying-100k",
  "maxItems": 200,
  "maxFilingsScanned": 1500
}
```

#### Example 3: Option exercises and the sales and tax withholding around them, with the option rows

```json
{
  "tickers": ["NVDA", "AVGO", "AMD"],
  "daysBack": 5,
  "transactionCodes": ["M", "S", "F"],
  "includeDerivative": true,
  "includeAmendments": true,
  "watchName": "chip-option-exercises",
  "maxItems": 300
}
```

### Input reference

| Field | Type | Default | What it does |
|---|---|---|---|
| `tickers` | string\[] | \[] | Stock symbols. Mapped to issuer CIKs with the SEC's public company ticker file and applied to the daily index before any download. |
| `issuerCiks` | string\[] | \[] | Issuer CIKs, for companies without a ticker. Combined with `tickers`. |
| `daysBack` | int 1–10 | 1 | Past business days of daily index files to read, plus today's index if already published. |
| `transactionCodes` | enum\[] | \["P","S"] | Form 4 codes to output. An empty list means every code. |
| `onlyOpenMarket` | bool | false | Shortcut for codes P and S only, overriding `transactionCodes`. |
| `minTransactionValue` | int USD | none | Minimum shares × price. Rows without a price are left out when set. |
| `insiderRoles` | enum\[] | all | `director`, `officer`, `tenPercentOwner`, `other`; any match counts. |
| `includeDerivative` | bool | false | Also output derivative-table rows (options, RSUs, warrants, convertibles). |
| `includeAmendments` | bool | false | Also read 4/A amendments. |
| `onlyNew` | bool | true | Output only transactions this watch has not output before. |
| `watchName` | string | "default" | Memory key; stored in the named key-value store `form4-watch-<name>`. |
| `maxItems` | int 1–5000 | 200 | Hard cap on rows per run; the rest is left for the next run. |
| `maxFilingsScanned` | int 1–5000 | 300 | Hard cap on filings downloaded per run, so whole-market runs stay short. |
| `userAgentContact` | string | none | Optional contact (your e-mail) for the User-Agent header sent to www.sec.gov. |

### Pricing

Pay per event. You pay for rows actually delivered, plus a small start fee.

| Event | Price | When |
|---|---|---|
| Actor start | **$0.005** | Once per run, even when nothing is new |
| `transaction` | **$0.003** | Per row in the dataset (one transaction) |

**What a typical watch costs.** A daily watch on a handful of tickers that averages 5 new transactions a day: 5 × $0.003 + $0.005 = **$0.02 a day, about $0.60 a month**. A quiet day costs $0.005. A whole-market feed of 50 transactions a day costs about $0.155 a day. Compute is included, there are no proxy charges, and the run stops itself before exceeding the spending limit you set on the run (`Maximum cost per run` in Apify). Filtered-out transactions are never charged.

### Data source and how the Actor behaves

**Source: U.S. Securities and Exchange Commission, EDGAR Form 4 filings (public information).** The SEC states that information presented on sec.gov is public information that may be copied or further distributed, and asks for appropriate citation of the SEC as the source.

The Actor reads only documented, machine-readable files: the **daily form index** (`/Archives/edgar/daily-index/YYYY/QTRn/form.YYYYMMDD.idx`, one request per business day), the **company ticker file** (`/files/company_tickers.json`, one request, only when you enter tickers), and for each Form 4 it needs, the filing folder's **`index.json`** and the **Form 4 XML** it lists (two requests per filing). It does not crawl web pages, does not log in and does not use a browser. Requests carry a declared User-Agent (`Form4InsiderWatch/0.1 ...`, with your contact if you provide one) and accept gzip, are spaced at **5 per second** (half the SEC's published ceiling of 10), time out after 30 s, and transient errors (429, 5xx, network) are retried at most 3 times with backoff. If the site's automated-traffic guard answers, the run stops cleanly, keeps the rows already pushed and tells you to wait before the next run.

A Form 4 is listed in the daily index once per filer (under the company and under each insider), so the Actor groups those lines by accession number and downloads each filing once. If one filing's XML does not look like a Form 4, that filing is skipped and counted in `errors`; the run continues and tries it again next time. If the daily index itself no longer matches the documented layout, the run fails with a clear message instead of emitting empty results.

**Timing.** Rows appear after the SEC publishes the filing in its daily index, which happens in the evening (US Eastern) of the day the filing was made. Insiders have two business days after a trade to file. So a trade usually shows up in this Actor one to three business days after it happened. This is not a live feed.

**People named in filings.** Insider names, CIKs and roles are what the filer reported publicly on the form; the Actor outputs them as filed and nothing more.

### Limitations

- **Whole-market runs.** Without tickers, a single business day has hundreds of Form 4 filings and can exceed 1,000 on busy days (in our test week, 210 to 480 a day), most of them grants, option exercises and tax withholding. Every filing has to be downloaded to see its codes, so `maxFilingsScanned` (default 300) caps the downloads per run. The filings beyond the cap are left for the next run, but a daily schedule with `daysBack` 1 moves on to the next day: for a complete whole-market feed set `maxFilingsScanned` to 1500 or `daysBack` to 2.
- Purchases (code P) are rare compared with sales and grants; a whole-market day may have only a handful, often clustered in a few filings.
- `P` and `S` cover open-market **and** private purchases and sales, as the form defines them.
- Prices are per share as filed. Many filers report a weighted average price and give the range in a footnote.
- The daily index lists filings alphabetically by filer. With a low `maxItems` or `maxFilingsScanned` the run stops part-way through a day; the next run continues where the watch left off, row by row.
- The first run of a new `watchName` reports everything in the window as new. That is expected; lower `daysBack` or `maxItems` if you prefer.
- The watch memory lives in a named key-value store in your account called `form4-watch-<watchName>`. Deleting it resets the watch. Filings not seen for 180 days are forgotten automatically.
- Tickers come from the SEC's company ticker file, which lists current symbols. Delisted or renamed symbols may not resolve; use `issuerCiks` for those. Unknown tickers are listed in `RUN_SUMMARY`.
- Holdings rows (positions reported without a transaction) are not output.

### Integrations and automation

Works with every Apify integration: schedules, webhooks, Google Sheets, Slack, email, Zapier, Make, n8n, LangChain and the Apify API and MCP server. Because the output is already the delta, a "new dataset items" trigger maps one-to-one to "new insider transactions".

Typical pipelines:

- **Slack alert on insider buying:** daily at 8 am, codes P, minimum value $50,000; post `ticker`, `reportingOwnerName`, `officerTitle`, `shares`, `pricePerShare`, `value` and `filingIndexUrl`.
- **Watchlist sheet:** append rows for your tickers to Google Sheets and pivot by insider or by month.
- **Warehouse:** load the dataset into BigQuery or Postgres keyed on `accessionNumber` + `rowIndex`.

### FAQ

**Is this investment advice?** No. The Actor delivers data as filed. Insider transactions have many reasons (taxes, diversification, pre-arranged 10b5-1 plans) and say nothing on their own about future prices.

**Is this data legal to use?** Form 4 filings are public records published by the SEC, which states the information may be copied and further distributed with appropriate citation. You remain responsible for how you use the data.

**Why is a trade I read about missing?** It may not have been filed yet (two business days after the trade), the day's index may not be published yet, it may be an amendment (turn on `includeAmendments`), a derivative row (turn on `includeDerivative`), another code, or your filters, `maxItems` or `maxFilingsScanned` left it out. Check `RUN_SUMMARY` for the counts.

**Why does one filing give several rows?** Each transaction line on the form is a row. Large sales are often reported as many lines at different prices.

**What do P and S cover that A, M and F do not?** P and S are purchases and sales. A is a grant or award from the company, M an option exercise or conversion, F shares withheld to pay the exercise price or tax. Those are usually not trading decisions, which is why they are off by default.

**Can I track several watchlists?** Yes. Give each its own `watchName`; each keeps its own memory.

### Support

Open an issue on the Actor's **Issues** tab in Apify Console with your input and run ID. Feature requests welcome, especially new filters or output fields.

# Actor input Schema

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

Stock symbols of the companies to watch, e.g. AAPL, MSFT, NVDA. Mapped to the issuer's CIK with the SEC's public company ticker file, and used to pick filings from the daily index BEFORE anything is downloaded. Leave empty (and Issuer CIKs empty) for the whole market.

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

Optional Central Index Keys of issuers to watch (e.g. 320193 for Apple), for companies without a listed ticker. Combined with Tickers (either matches).

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

How many past business days of daily filing index files to read, plus today's if it has already been published (each day's index appears in the evening, US Eastern time). 1 is right for a daily schedule.

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

Which kinds of transactions to output (Form 4 transaction codes). Default: P and S (purchases and sales on the open market or in private deals). Clear the list to output every code.

## `onlyOpenMarket` (type: `boolean`):

Shortcut: keep only codes P and S, whatever is selected under Transaction codes. Grants, option exercises, tax withholding and gifts are left out.

## `minTransactionValue` (type: `integer`):

Keep only transactions where shares × price per share is at least this amount. Transactions reported without a price (value unknown) are left out when this is set. Leave empty for no minimum.

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

Keep only transactions by insiders with ANY of these roles, as ticked on the form. Leave empty for all.

## `includeDerivative` (type: `boolean`):

Also output rows from the derivative table (options, warrants, RSUs, convertible notes), with exercise price, expiration and underlying shares. Off by default: only transactions in the shares themselves.

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

Also read amended filings (form 4/A), which correct an earlier Form 4. Off by default.

## `onlyNew` (type: `boolean`):

Remember every transaction this watch has output (by filing and row) and output only transactions not seen before. Quiet runs output nothing and cost only the start fee. Turn off to re-output everything in the window.

## `watchName` (type: `string`):

Name of the saved watch. Each watch keeps its own memory (named key-value store form4-watch-<name>), so several watches ('big-tech', 'bank-directors') can run side by side.

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

Hard cap on output rows per run. The run also stops early if your Apify spending limit for this run would be exceeded. Transactions beyond the cap are left for the next run.

## `maxFilingsScanned` (type: `integer`):

Hard cap on Form 4 filings downloaded per run. Without tickers a single business day has hundreds to well over a thousand Form 4 filings, most of them grants and option exercises; this cap keeps whole-market runs short. Filings beyond the cap are left for the next run.

## `userAgentContact` (type: `string`):

www.sec.gov asks automated tools to identify themselves with contact details. If you enter your e-mail address, requests are sent as 'Form4InsiderWatch/0.1 <your e-mail>'; otherwise the Actor's default identification is used. It is sent only to www.sec.gov and appears in your own run log and run summary.

## Actor input object example

```json
{
  "tickers": [
    "AAPL",
    "MSFT",
    "NVDA",
    "TSLA",
    "AMZN"
  ],
  "issuerCiks": [],
  "daysBack": 1,
  "transactionCodes": [
    "P",
    "S"
  ],
  "onlyOpenMarket": false,
  "insiderRoles": [],
  "includeDerivative": false,
  "includeAmendments": false,
  "onlyNew": true,
  "watchName": "default",
  "maxItems": 200,
  "maxFilingsScanned": 300
}
```

# Actor output Schema

## `transactions` (type: `string`):

No description

## `runSummary` (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",
        "MSFT",
        "NVDA",
        "TSLA",
        "AMZN"
    ],
    "issuerCiks": [],
    "insiderRoles": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("glaciological_huddle/form4-insider-watch").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",
        "MSFT",
        "NVDA",
        "TSLA",
        "AMZN",
    ],
    "issuerCiks": [],
    "insiderRoles": [],
}

# Run the Actor and wait for it to finish
run = client.actor("glaciological_huddle/form4-insider-watch").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",
    "MSFT",
    "NVDA",
    "TSLA",
    "AMZN"
  ],
  "issuerCiks": [],
  "insiderRoles": []
}' |
apify call glaciological_huddle/form4-insider-watch --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,glaciological_huddle/form4-insider-watch"
        }
    }
}
```

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/0NbxqauycleS8EBRY/builds/HAhOaWPriAMZrINOG/openapi.json
