# OpenInsider Trades Scraper (`axiomworks/openinsider-insider-trading-scraper`) Actor

Scrape OpenInsider trade tables and return one item per transaction, with filing and trade dates, ticker, company, insider, transaction type, price, shares, and value. Scrape ticker, insider, screener, and preset pages; cluster pages can return grouped company trades.

- **URL**: https://apify.com/axiomworks/openinsider-insider-trading-scraper.md
- **Developed by:** [Axiom Works](https://apify.com/axiomworks) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.83 / 1,000 results

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

## OpenInsider Trades Scraper

**Returns:** one row per insider trade with filingDate, tradeDate, ticker, companyName, insiderName, tradeType, price, and value.
**Input:** `{"tickers":["AAPL"],"filingPeriod":"730","maxItems":20}`
**Best for:** insider trade monitoring, research datasets, and SEC Form 4 review.

```json
{"filingDate":"2026-10-08 18:30:32","tradeDate":"2026-10-06","ticker":"AAPL","companyName":"Apple Inc.","insiderName":"Newstead Jennifer","tradeType":"S - Sale","price":332.01,"value":-796492}
```

### What does OpenInsider Trades Scraper do?

OpenInsider Trades Scraper extracts public insider transaction rows from OpenInsider trade tables. It accepts ticker symbols, insider names or CIKs, and OpenInsider page URLs. You can also leave those targets empty and use its all market screener. The result is a dataset with one row per transaction or, for cluster pages, one row per grouped company trade. The opening example was collected locally on October 13, 2026. The OpenInsider scraper reads the table as displayed on the site and carries the SEC Form 4 link when the row provides one. It does not require a login.

A typical use is to look up transactions for one company over a specified filing period. Another is to capture a preset page, such as recent purchases, on a schedule and compare its stable record IDs between runs. A third is to screen several tickers or insider names while limiting output to a known number of records. The Actor uses the OpenInsider table rather than downloading SEC documents, so values represent the site's summary of those filings. Dates and transaction types are kept as displayed; numeric values are converted from the formatted table text.

The target site serves its public trade pages over HTTP. If you supply an OpenInsider HTTPS link, the Actor converts it to HTTP before requesting it. OpenInsider's web pages may change, and individual records may be corrected or added after a filing. For repeat monitoring, compare the stable `id` and review `pageUrl` or `secFormUrl` for context. This Actor is an independent tool and is not affiliated with OpenInsider or the SEC.

### What data can you get?

Each output item includes an `id` and `sourceUrl`. `sourceUrl` is the SEC Form 4 URL when the trade row links to one; otherwise it is the OpenInsider page URL. Fields unavailable for a given page type are `null`. In particular, cluster pages have grouped rows without a named insider or a Form 4 link. The Actor maps table columns by their visible headings because ticker, screener, and cluster pages show different columns.

| Field | What it contains |
| --- | --- |
| `id` | Stable transaction identifier built from filing and trade details, or a grouped row fallback. |
| `sourceUrl` | SEC Form 4 link when present, otherwise the source page. |
| `filingDate` | Filing date and time shown in the table. |
| `tradeDate` | Transaction date shown in the table. |
| `ticker` | Issuer's stock symbol. |
| `companyName` | Company name from the row or the page heading. |
| `insiderName` | Insider name, when the row represents a named person. |
| `insiderTitle` | Role or title shown for the insider. |
| `insiderUrl` | OpenInsider insider page link. |
| `insiderCik` | CIK extracted from the insider link. |
| `tradeType` | Full displayed transaction type, such as `S - Sale`. |
| `tradeTypeCode` | First code letter of the transaction type. |
| `price` | Share price as a number. |
| `quantity` | Signed number of shares traded. |
| `sharesOwnedAfter` | Shares owned after the trade. |
| `ownershipChange` | Displayed change, including `New` or a percentage. |
| `ownershipChangePct` | Numeric percentage when the display can be converted. |
| `value` | Signed transaction value as a number. |
| `filingFlags` | Letters in the table's `X` column, when present. |
| `industry` | Industry on grouped or cluster pages. |
| `insiderCount` | Number of insiders on grouped or cluster pages. |
| `secFormUrl` | SEC Form 4 URL linked from the filing date, when present. |
| `issuerCik` | Issuer CIK extracted from the SEC link. |
| `accessionNumber` | Accession number extracted from the SEC link. |
| `pageUrl` | OpenInsider page that supplied the row. |
| `scrapedAt` | Time the Actor collected the row in ISO format. |

The table is a practical research index. `value` and `quantity` retain negative signs for sales when the site displays them. `ownershipChangePct` is `null` for labels such as `New` that do not represent an ordinary numeric percentage. Empty cells remain `null`, so filters in downstream spreadsheets or databases can distinguish a missing value from zero. The output does not include a prediction of future stock movement or any investment recommendation.

### How to use

Open the Actor input form and choose a target. For company research, enter one or more symbols in `tickers`, or use `ticker` for one symbol or a comma separated string. For person research, enter an insider name or CIK in `insiders`. To use a particular OpenInsider preset or an existing screener link, paste it into `startUrl`; `startUrls` accepts a list of URL strings or `{ "url": "..." }` objects. Links without a scheme and `www` or HTTPS OpenInsider links are normalized. You can combine targets in a single run. Results from overlapping queries are deduplicated by `id` and returned in the order they are encountered.

Set `maxItems` to the exact number of records you want, from 1 to 10000. The cap is shared across all tickers, insiders and URLs; duplicate IDs count once. The Actor stops adding records at that limit, even if a page has more rows. Screener queries can continue to additional pages until the limit is met or there are no more rows. Preset pages, ticker pages, and insider pages are read once because their `page=2` variants repeat the same rows. When you need more than the first page of a large screener, increase `maxItems` and keep the filters narrow enough for a useful dataset.

Choose transaction types and optional filing or trade dates, value thresholds, price limits, or roles. These filters apply to generated screener queries for tickers, insiders, and an all market search. A `startUrls` screener URL keeps the filters already in that URL; the Actor manages only its page size and page number. Preset and ticker page links are read as they appear. The homepage reads all its trade tables. If a valid target has no trades, the run succeeds with zero items and a status message suggesting a broader query. If the site is temporarily blocked, retries use backoff and fresh proxy sessions when a proxy is configured.

### Input

| Field | Usage |
| --- | --- |
| `tickers` | List of stock symbols or issuer CIKs. |
| `ticker` | One symbol or a comma separated symbol string. |
| `insiders` | Insider names or CIKs to search. |
| `startUrls` | OpenInsider screener, preset, ticker, insider, or homepage URL list. |
| `startUrl` | One OpenInsider URL, with or without a scheme. |
| `transactionTypes` | Types including `purchase`, `sale`, `grant`, `gift`, and other supported Form 4 codes. |
| `filingPeriod` | Filing lookback in days; `0` means all dates. |
| `filingDateFrom` | Start of an explicit filing date interval, `YYYY-MM-DD`. |
| `filingDateTo` | End of an explicit filing date interval, `YYYY-MM-DD`. |
| `tradePeriod` | Trade date lookback in days; `0` disables this filter. |
| `tradeDateFrom` | Start of an explicit trade date interval, `YYYY-MM-DD`. |
| `tradeDateTo` | End of an explicit trade date interval, `YYYY-MM-DD`. |
| `minTradeValueK` | Minimum absolute value in thousands of USD. |
| `maxTradeValueK` | Maximum absolute value in thousands of USD. |
| `minPrice` | Minimum share price. |
| `maxPrice` | Maximum share price. |
| `insiderRoles` | Role filters such as `ceo`, `cfo`, `director`, or `officer`. |
| `sortBy` | Filing date, trade date, ticker, or trade value. |
| `maxItems` | Global output cap, 1 to 10000, default 50. |
| `proxyConfiguration` | Optional Apify Proxy settings; direct access is the default. |

A common request for company trades is:

```json
{
  "tickers": ["AAPL"],
  "filingPeriod": "730",
  "transactionTypes": ["purchase", "sale"],
  "maxItems": 20
}
```

For a preset page, use `{"startUrls":[{"url":"http://openinsider.com/latest-insider-purchases-25k"}],"maxItems":20}`. For a screener with a named insider, use `{"insiders":["Huang Jen Hsun"],"filingPeriod":"365","maxItems":20}`. `filingDateFrom` overrides `filingPeriod`; `tradeDateFrom` overrides `tradePeriod`. When no target is supplied, the Actor runs an all market screen using the selected filters. A malformed URL is an input error; a well formed OpenInsider URL with no matching rows simply returns no items.

### Output

This record came from a local AAPL run. It illustrates the complete numeric parsing and the link back to the SEC filing. Other records can have null optional fields, and grouped cluster pages use `industry` and `insiderCount` instead of named insider fields.

```json
{
  "id": "0001140361-26-039158-AAPL-1780525-2026-10-06-S--2399",
  "sourceUrl": "http://www.sec.gov/Archives/edgar/data/320193/000114036126039158/xslF345X03/form4.xml",
  "filingDate": "2026-10-08 18:30:32",
  "tradeDate": "2026-10-06",
  "ticker": "AAPL",
  "companyName": "Apple Inc.",
  "insiderName": "Newstead Jennifer",
  "insiderTitle": "SVP, GC, Government Affairs",
  "tradeType": "S - Sale",
  "price": 332.01,
  "quantity": -2399,
  "sharesOwnedAfter": 39593,
  "ownershipChange": "-6%",
  "value": -796492,
  "pageUrl": "http://openinsider.com/screener?s=AAPL&fd=730&xp=1&xs=1&sortcol=0&cnt=100&page=1"
}
```

Export the dataset as JSON, CSV, or Excel in Apify. The field names stay the same across formats. The first result can change as new filings appear, so treat this example as a sample shape and use the live output for current research. A stable `id` helps compare scheduled runs without counting the same transaction twice within one run.

### How much does it cost?

The Actor is charged per result that is saved to the dataset. Set `maxItems` to control the largest possible result count for a run. A zero result run adds no result records. The current charge details are shown on the Actor's Pricing tab. The Actor does not add a separate charge for opening a screener page or following its pagination; output items are the billing unit. Keep a narrow filing period or ticker filter when you only need a small sample, and increase the cap for a broader export.

### Use with AI agents (MCP)

The Apify MCP server can expose this Actor as a tool to an AI agent. Configure the server at `https://mcp.apify.com/?tools=axiomworks/openinsider-insider-trading-scraper`. The agent then sees the input schema and can submit a ticker, an insider, or a page URL. You can ask it to collect records and summarize fields that actually appear in the dataset.

Example prompts include “Find the latest twenty AAPL insider transactions and show their filing dates, names, trade types, quantities, and SEC links,” “Collect recent purchases from the OpenInsider preset page and group the output by ticker,” and “Get the most recent CEO and CFO purchase rows with a minimum trade value threshold.” These prompts request data collection and simple summaries. They do not imply that the Actor validates the economic meaning of a trade or provides financial advice.

An agent can use `id` to avoid repeated records, `sourceUrl` to retain provenance, and `scrapedAt` to label when the data was collected. It should keep null optional fields as null rather than inventing missing insider names on grouped pages. For a current snapshot, run the Actor again; old runs are stored datasets, not live queries.

### Integrations and API

Use the Actor ID `axiomworks/openinsider-insider-trading-scraper` in Apify API clients. The examples below submit the same AAPL query. Each returns a run that produces dataset items. Your Apify client supplies authentication through its normal environment or configuration; do not paste credentials into saved input files.

Python:

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("axiomworks/openinsider-insider-trading-scraper").call(run_input={"tickers": ["AAPL"], "maxItems": 20})
items = list(client.dataset(run["defaultDatasetId"]).iterate_items())
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('axiomworks/openinsider-insider-trading-scraper').call({ tickers: ['AAPL'], maxItems: 20 });
const items = await client.dataset(run.defaultDatasetId).listItems();
```

cURL:

```bash
curl -X POST 'https://api.apify.com/v2/acts/axiomworks~openinsider-insider-trading-scraper/runs' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_APIFY_TOKEN' \
  -d '{"tickers":["AAPL"],"maxItems":20}'
```

For scheduled work, save one input configuration for each question you want to answer. A daily run with `maxItems` set to a modest number captures the current top of a preset page. A wider date range supports a historical export. Keep the returned dataset ID alongside your run metadata so your downstream process can retrieve exactly the rows produced by that run.

### FAQ

**Can I search several tickers?** Yes. Put symbols in `tickers`; the Actor sends them to the screener and deduplicates overlapping output. You can also supply a comma separated string. If you need separate runs or separate datasets per ticker, schedule one input per ticker.

**Can I use an OpenInsider URL I copied from my browser?** Yes, if it points to an OpenInsider trade table. HTTPS links and `www` links are normalized to the HTTP host the site serves. Other hosts are skipped. A screener URL keeps its search filters while page size and page number are managed by the Actor.

**What happens when nothing matches?** The run succeeds with no dataset items and a status message. Try a wider filing period, fewer role or value filters, another symbol, or a known preset page. The Actor never inserts a placeholder item for an empty table.

**Are the dates in UTC?** `filingDate` is preserved as displayed on OpenInsider. `scrapedAt` is an ISO timestamp generated during collection. Interpret the source's displayed filing time in its site context rather than assuming it is UTC.

**Why are some fields null?** OpenInsider tables differ by page. Cluster rows are grouped company rows, so `insiderName`, `insiderTitle`, and `secFormUrl` may not exist. An ordinary transaction can also have an empty flag cell or an ownership label that cannot be converted to a percentage.

**Can I request exactly one item?** Yes. Set `maxItems` to 1. The Actor stops after saving one qualifying row and does not charge for rows it did not save. The first row is based on the requested page and sort order.

**Does this fetch the SEC document?** No. The result includes the SEC Form 4 URL when OpenInsider links one from the row. The dataset contains OpenInsider's table values, including the link, and does not parse the full SEC XML filing.

### Is it legal to scrape OpenInsider?

This Actor collects public pages that are accessible without a login. Laws and site terms can differ by location and use case. Review the site's terms and applicable rules for your own use, keep collection volumes modest, and avoid presenting the data as verified investment advice. OpenInsider and the SEC can correct filings or change page layouts, so retain source links and check important facts against the source. This Actor is independent and has no affiliation with OpenInsider.

### Feedback

If a table layout changes or a field starts returning null unexpectedly, share the input you used, the affected `pageUrl`, and a short sample of the returned item through the Actor's Apify feedback channel. Do not include private credentials or unrelated personal information. A useful report identifies the visible table heading and the output field you expected. For an empty result, include the target ticker or page URL and the filters; that makes it possible to distinguish a genuinely empty search from a parsing problem.

# Actor input Schema

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

Stock symbols or issuer CIKs, e.g. \["AAPL"] or \["320193"]. Also accepts comma/space-separated strings and aliases ticker, symbols, searchTerms, query. Combined with insiders and startUrls; leave all targets empty for an all-market screener.

## `ticker` (type: `string`):

One stock symbol or comma/space-separated symbols, e.g. "AAPL,MSFT". Adds to tickers; default empty. Generated screener filters apply.

## `insiders` (type: `array`):

Insider names or CIKs, e.g. \["Huang Jen Hsun"] or \["1197647"]. Each creates a screener search with the selected filters. Default empty; shares maxItems with other targets.

## `startUrls` (type: `array`):

OpenInsider URLs, e.g. \[{"url":"http://openinsider.com/latest-cluster-buys"}]. Also accepts URL strings. Screener, preset, ticker, insider and homepage tables supported. HTTPS, www and missing schemes normalize to HTTP. URL filters are preserved; separate filter inputs do not apply. Other hosts are skipped.

## `startUrl` (type: `string`):

One OpenInsider page URL, e.g. "https://www.openinsider.com/AAPL". Adds to startUrls; default empty. URL filters are preserved; separate filter inputs do not apply. Missing schemes accepted; other hosts skipped.

## `transactionTypes` (type: `array`):

Transaction names or codes for generated screeners, e.g. \["purchase","sale"] or \["P","S"]. Default purchase and sale. Accepts purchase, sale, grant, saleToIssuer, gift, tax, optionExercise, optionExerciseOther, convertedDerivative, inherited, or P/S/A/D/G/F/M/X/C/W.

## `filingPeriod` (type: `string`):

Filing lookback in days for generated screeners, e.g. "730"; "0" means all dates. When omitted: 730 for tickers/insiders, 30 for all-market searches. The form default is 730. filingDateFrom overrides it.

## `filingDateFrom` (type: `string`):

Earliest filing date, e.g. "2026-01-01". Default empty. Overrides filingPeriod for generated screeners; filingDateTo defaults to today.

## `filingDateTo` (type: `string`):

Latest filing date, e.g. "2026-10-01". Used with filingDateFrom; omitted or empty means today when From is set. Without From it does not filter.

## `tradePeriod` (type: `string`):

Trade-date lookback in days for generated screeners, e.g. "30". Default "0" means no trade-date filter. tradeDateFrom overrides it.

## `tradeDateFrom` (type: `string`):

Earliest trade date, e.g. "2026-01-01". Default empty. Overrides tradePeriod for generated screeners; tradeDateTo defaults to today.

## `tradeDateTo` (type: `string`):

Latest trade date, e.g. "2026-10-01". Requires tradeDateFrom; omitted or empty means today when From is set.

## `minTradeValueK` (type: `number`):

Minimum absolute trade value in thousands of USD, e.g. 25 means 25000 USD. Omit for no minimum.

## `maxTradeValueK` (type: `number`):

Maximum absolute trade value in thousands of USD, e.g. 100 means 100000 USD. Omit for no maximum.

## `minPrice` (type: `number`):

Minimum share price in USD, e.g. 5. Omit for no minimum.

## `maxPrice` (type: `number`):

Maximum share price in USD, e.g. 100. Omit for no maximum.

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

Role names for generated screeners, e.g. \["ceo","cfo"]. Default \[] means no role filter. Accepts officer, ceo, cfo, coo, president, chairman, generalCounsel, vp, director, tenPercentOwner, other.

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

Sort field for generated screeners: filingDate, tradeDate, ticker or tradeValue; e.g. "tradeValue". Default filingDate.

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

Maximum unique trade rows across all tickers, insiders and URLs combined, e.g. 20. Integer 1-10000, default 50. Stops at this shared cap; fewer rows may match. Duplicate ids count once. Valid empty or blocked targets return no error rows; broaden filters or retry with proxy.

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

Proxy settings for OpenInsider requests, e.g. {"useApifyProxy":false} for direct access (default), or {"useApifyProxy":true}. Blocked requests retry with backoff and fresh configured proxy sessions; if still blocked, return zero rows for that target and guidance to retry.

## Actor input object example

```json
{
  "tickers": [
    "AAPL"
  ],
  "ticker": "",
  "insiders": [],
  "startUrls": [],
  "startUrl": "",
  "transactionTypes": [
    "purchase",
    "sale"
  ],
  "filingPeriod": "730",
  "filingDateFrom": "",
  "filingDateTo": "",
  "tradePeriod": "0",
  "tradeDateFrom": "",
  "tradeDateTo": "",
  "insiderRoles": [],
  "sortBy": "filingDate",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `trades` (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"
    ],
    "transactionTypes": [
        "purchase",
        "sale"
    ],
    "filingPeriod": "730",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("axiomworks/openinsider-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"],
    "transactionTypes": [
        "purchase",
        "sale",
    ],
    "filingPeriod": "730",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("axiomworks/openinsider-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"
  ],
  "transactionTypes": [
    "purchase",
    "sale"
  ],
  "filingPeriod": "730",
  "maxItems": 20
}' |
apify call axiomworks/openinsider-insider-trading-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,axiomworks/openinsider-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/mbzdxHx8OYDgxc8Zp/builds/Kc0ITHZ7n6fhnVi1n/openapi.json
