# SEC Form 4 Insider Trades Scraper (`devilscrapes/sec-form-4-insider-trades-scraper`) Actor

Parses SEC Form 4 insider-transaction filings into transaction-level rows -- who traded, how many shares, at what price, and under which transaction code (buy, sell, award, exercise) -- from the ownership XML. One row per trade, not per filing; joint filings handled correctly.

- **URL**: https://apify.com/devilscrapes/sec-form-4-insider-trades-scraper.md
- **Developed by:** [DevilScrapes](https://apify.com/devilscrapes) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

<div align="center">
  <img src=".actor/icon.svg" width="160" alt="Devil Scrapes mark" />

## SEC Form 4 Insider Trades Scraper

**💰 $2.70 / 1 000 results**  ·  pay only for results  ·  no credit card to try

*We do the dirty work so your dataset stays clean.* 😈

Parses SEC Form 4 insider-transaction filings into transaction-level rows -- who traded, how many shares, at what price, and under which transaction code (buy, sell, award, exercise) -- from the ownership XML. One row per trade, not per filing; joint filings handled correctly.

</div>

***

### 🎯 What this scrapes

Every SEC Form 4 filing carries an <ownershipDocument> XML body listing the actual insider trades behind the filing -- who traded, how many shares, at what price, under which transaction code, and what they own afterward. Most EDGAR tooling stops at the filing index (form type, date, accession number); this Actor goes one level deeper and parses that XML directly, resolving tickers to CIKs, walking each issuer's recent Form 4 filings, and emitting one row per buy, sell, award, or option-exercise line item -- joint filings included, with every reporting owner correctly attributed to their share of each transaction.

### 🔥 What we handle for you

- 🔁 **Retries with exponential backoff** on `429` / `5xx` and honours `Retry-After` -- we never hammer SEC's servers into a block.
- 🧱 **Rate-limit-aware pacing** -- a shared request-interval floor keeps every run inside SEC's ~10 req/s polite-use ceiling, even across concurrent runs.
- 🧾 **Transaction-level parsing, not just a filing index** -- every buy, sell, award, and exercise line item, with footnote-only fields honestly reported as `null` instead of guessed.
- 🧊 **Joint filings handled correctly** -- every reporting owner on a multi-owner Form 4 gets attributed rows, never silently dropped.
- 🧊 **Clean, typed dataset rows** -- Pydantic-validated, ISO-8601 timestamps, stable accession-number IDs.
- 💰 **Pay-Per-Event pricing** -- you only pay for transaction rows that land in your dataset. No data, no charge (beyond the small warm-up fee).

### 💡 Use cases

- **Insider-trading signal feeds** -- quant and fintech shops ingesting transaction-level buy/sell data as a raw factor input.
- **Activist and executive-conviction tracking** -- flag large open-market buys (code P) by officers and directors across a watchlist.
- **Equity research workflows** -- pull every recent insider transaction for a covered issuer without hand-parsing XML.
- **Financial media and newsletters** -- surface notable Form 4 activity (large sells, cluster buying) for a daily brief.
- **Compliance and governance monitoring** -- audit officer/director trading windows against blackout-period policy.

### ⚙️ How to use it

1. Click **Try for free** at the top of the page.
2. Fill in the input form — most fields have sensible defaults.
3. Click **Start**. Output streams into the run's dataset.
4. Export from **Storage → Dataset** as JSON, CSV, or Excel — or fetch via the API.

### 📥 Input

| Field | Type | Required | Default | Notes |
|---|---|:--:|---|---|
| `tickers` | `array` | **yes** | \['AAPL', 'TSLA'] | Ticker symbols (e.g. <code>AAPL</code>) or 10-digit CIKs to sweep for Form 4 insider-transaction filings. We resolve… |
| `lookbackDays` | `integer` | no | 90 | Only include Form 4 filings with a filing date within this many days of run start. |
| `maxFilingsPerIssuer` | `integer` | no | 50 | Cap on the number of Form 4 filings fetched and parsed per issuer -- bounds egress on issuers with heavy… |
| `includeDerivative` | `boolean` | no | True | Include derivative-table transactions -- stock options, RSUs, and similar -- as output rows. |
| `includeNonDerivative` | `boolean` | no | True | Include non-derivative-table transactions -- common-stock buys and sells -- as output rows. |
| `userAgent` | `string` | no | 'DevilScrapes-Form4/1.0 (contact: apify.com/DevilScrapes)' | SEC requires a descriptive User-Agent with contact info on every request. Default identifies as Devil Scrapes; replace… |
| `proxyConfiguration` | `object` | no | {'useApifyProxy': True} | Apify Proxy configuration. SEC EDGAR has no anti-bot wall -- this is a fleet-standard courtesy that helps smooth the… |

#### Example input

```json
{
  "tickers": [
    "AAPL"
  ],
  "lookbackDays": 30,
  "maxFilingsPerIssuer": 3,
  "includeDerivative": true,
  "includeNonDerivative": true,
  "userAgent": "DevilScrapes-Form4/1.0 (contact: apify.com/DevilScrapes)",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

### 📤 Output

Every row is one dataset item.

| Field | Type | Notes |
|---|---|---|
| `issuer_cik` | `string` | Issuer's 10-digit CIK (zero-padded). |
| `issuer_name` | `string` | Issuer (company) name. |
| `issuer_ticker` | `string` | Issuer's trading symbol, when present on the filing. |
| `owner_cik` | `string` | Reporting owner's 10-digit CIK (zero-padded). |
| `owner_name` | `string` | Reporting owner (insider) name. |
| `is_director` | `boolean` | Whether the reporting owner is a director. |
| `is_officer` | `boolean` | Whether the reporting owner is an officer. |
| `is_ten_percent_owner` | `boolean` | Whether the reporting owner holds 10%+ of the issuer's stock. |
| `officer_title` | `string` | Officer title (e.g. "CEO"), when is\_officer is true. |
| `transaction_date` | `string` | Transaction date (YYYY-MM-DD). Null when the date is footnote-only. |
| `transaction_code` | `string` | SEC single-letter transaction code (P, S, A, M, F, G, C, X, etc.). |
| `transaction_code_label` | `string` | Plain-English label for transaction\_code (e.g. "Grant/award/other acquisition"). |
| `is_derivative` | `boolean` | True when this row came from the derivativeTransaction table, false for nonDerivativeTransaction. |
| `security_title` | `string` | Security title (e.g. "Common Stock", "Restricted Stock Unit"). |
| `shares_transacted` | `number` | Number of shares transacted. Null when footnote-only. |
| `price_per_share` | `number` | Price per share (USD). Null when footnote-only (e.g. $0 RSU grants). |
| `transaction_value_usd` | `number` | Derived: shares\_transacted \* price\_per\_share, when both are present. |
| `acquired_disposed` | `string` | "A" (acquired) or "D" (disposed). |
| `shares_owned_after` | `number` | Shares owned by the reporting owner following the transaction. |
| `ownership_nature` | `string` | "D" (direct) or "I" (indirect) ownership. |
| `indirect_ownership_note` | `string` | Free-text nature-of-ownership note for indirect holdings (e.g. "By Trust"). |
| `underlying_security_title` | `string` | Underlying security title, derivative transactions only. |
| `underlying_shares` | `number` | Underlying share count, derivative transactions only. |
| `exercise_price` | `number` | Conversion or exercise price (USD), derivative transactions only. Null when footnote-only. |
| `exercise_date` | `string` | Exercise date, derivative transactions only. Null when footnote-only. |
| `expiration_date` | `string` | Expiration date, derivative transactions only. Null when footnote-only. |
| `accession_number` | `string` | SEC accession number the row came from (e.g. 0001140361-26-035362). |
| `filed_at` | `string` | Filing acceptance timestamp (ISO-8601), from the submissions index. |
| `period_of_report` | `string` | Period-of-report date for the filing. |
| `source_xml_url` | `string` | The ownership-XML URL actually fetched to produce this row. |
| `scraped_at` | `string` | ISO-8601 timestamp when this row was scraped. |

#### Example output

```json
{
  "issuer_cik": "0000320193",
  "issuer_name": "Apple Inc.",
  "issuer_ticker": "AAPL",
  "owner_cik": "0002148403",
  "owner_name": "Ternus John",
  "is_director": true,
  "is_officer": true,
  "is_ten_percent_owner": false,
  "officer_title": "CEO",
  "transaction_date": "2026-09-01",
  "transaction_code": "A",
  "transaction_code_label": "Grant/award/other acquisition",
  "is_derivative": true,
  "security_title": "Restricted Stock Unit",
  "shares_transacted": 7690.0,
  "price_per_share": null,
  "transaction_value_usd": null,
  "acquired_disposed": "A",
  "shares_owned_after": 7690.0,
  "ownership_nature": "D",
  "indirect_ownership_note": null,
  "underlying_security_title": "Common Stock",
  "underlying_shares": 7690.0,
  "exercise_price": null,
  "exercise_date": null,
  "expiration_date": null,
  "accession_number": "0001140361-26-035362",
  "filed_at": "2026-09-01T18:32:04-04:00",
  "period_of_report": "2026-09-01",
  "source_xml_url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126035362/form4.xml",
  "scraped_at": "2026-09-03T12:00:00+00:00"
}
```

### 💰 Pricing

Pay-Per-Event — you pay only when these events fire:

| Event | USD | What it is |
|---|---:|---|
| `actor-start` | $0.20 | One-off warm-up charge per run |
| `transaction-row` | $0.0025 | PPE event |

Example: 1 000 results at the rates above ≈ **$2.70**. No subscription, no minimum, no card to start — Apify gives every new account $5 of free credit.

### 🚧 Limitations

- Form 4 only -- Form 3 (initial ownership) and Form 5 (annual) filings are out of scope.
- No unbounded historical backfill -- lookback is bounded by `lookbackDays` and `maxFilingsPerIssuer`, with older filings pulled from an issuer's overflow submissions pages only as needed to cover the window.
- No "sweep everything filed today" firehose entry point -- you supply the tickers/CIKs to sweep; there's no reverse market-wide Form 4 stream in v1.
- Amended filings (form "4/A") are excluded by default.

### ❓ FAQ

**Is this the same as your SEC EDGAR Filings Scraper?**

No. That Actor returns one row per FILING (form type, date, accession number) across all SEC form types. This Actor returns one row per TRANSACTION -- parsed out of the Form 4 ownership XML body -- with shares, price, transaction code, and reporting-owner detail that the filing-index Actor doesn't have.

**Do I need a SEC EDGAR API key?**

No -- SEC EDGAR is free and keyless. It only requires a descriptive User-Agent with contact info, which we supply a sensible default for.

**What happens on a joint filing with multiple insiders?**

We emit one row per (reporting owner, transaction) pair -- every owner named on the filing is attributed to the transactions in that filing, never silently dropped.

**Why is price\_per\_share sometimes null?**

Some Form 4 fields (like a $0 RSU grant price) are only disclosed in a footnote, not the structured <value> element. We report those as null rather than guessing or defaulting to 0.

**Do you cover Form 3 or Form 5?**

Not in this version -- v1 is scoped to Form 4 only. Form 3 (initial ownership) and Form 5 (annual) filings are a candidate future enhancement.

### 💬 Your feedback

Spotted a bug, hit a weird edge case, or need a new field? Open an
issue on the Actor's **Issues** tab on Apify Console — we ship
fixes weekly and we read every report.

***

<div align="center">

Built by **[Devil Scrapes](https://apify.com/DevilScrapes)** 😈 — a small fleet of
opinionated public-data Actors. Honest pricing, real engineering, zero fine print.

</div>

# Actor input Schema

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

Ticker symbols (e.g. <code>AAPL</code>) or 10-digit CIKs to sweep for Form 4 insider-transaction filings. We resolve tickers to CIKs via SEC's company\_tickers.json.

## `lookbackDays` (type: `integer`):

Only include Form 4 filings with a filing date within this many days of run start.

## `maxFilingsPerIssuer` (type: `integer`):

Cap on the number of Form 4 filings fetched and parsed per issuer -- bounds egress on issuers with heavy insider-trading activity.

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

Include derivative-table transactions -- stock options, RSUs, and similar -- as output rows.

## `includeNonDerivative` (type: `boolean`):

Include non-derivative-table transactions -- common-stock buys and sells -- as output rows.

## `userAgent` (type: `string`):

SEC requires a descriptive User-Agent with contact info on every request. Default identifies as Devil Scrapes; replace with your own contact if you want SEC to associate requests with your organisation.

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

Apify Proxy configuration. SEC EDGAR has no anti-bot wall -- this is a fleet-standard courtesy that helps smooth the shared ~10 req/s polite-use rate ceiling across concurrent runs, not an anti-block measure.

## Actor input object example

```json
{
  "tickers": [
    "AAPL",
    "TSLA"
  ],
  "lookbackDays": 90,
  "maxFilingsPerIssuer": 50,
  "includeDerivative": true,
  "includeNonDerivative": true,
  "userAgent": "DevilScrapes-Form4/1.0 (contact: apify.com/DevilScrapes)",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# 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",
        "TSLA"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/sec-form-4-insider-trades-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",
        "TSLA",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/sec-form-4-insider-trades-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",
    "TSLA"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call devilscrapes/sec-form-4-insider-trades-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,devilscrapes/sec-form-4-insider-trades-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/C7gYJgbldJJothinb/builds/DgPdPTVOZWRyDzFt2/openapi.json
