# SEC EDGAR Scraper (`dami_studio/sec-edgar-scraper`) Actor

SEC EDGAR scraper API: search filings by keyword, or pull a company's filings by ticker or CIK. Rows hold the form type, company, CIK, filing and report dates, accession number, the matching document and a link to it. Full-text search returns one row per matching document. $2.00 per 1,000 filings.

- **URL**: https://apify.com/dami_studio/sec-edgar-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Integrations, Lead generation, Other
- **Features:** Limited permissions
- **Stats:** 3 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.94 / 1,000 items

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 EDGAR scraper for filings by phrase, or a company's filings by ticker or CIK**, one row
of filing data per document: the form type, the company, the CIK, the filing date, the accession number and a link
straight to the document.

One thing to know before you budget a run: full-text search returns a row per matching **document**,
not per filing. A 10-K whose exhibits all mention your phrase comes back as several rows, and each
one is charged.

| | |
|---|---|
| **Input** | A search phrase, or a list of tickers and CIKs |
| **Output** | One row per matching filing document: form, company, CIK, ticker, filing and report dates, accession number, document name and description, link |
| **Ceiling** | 10,000 filings per run |
| **Account needed** | None, and no SEC key |
| **Price** | $2.00 per 1,000 filings on the Free plan, a little less on paid plans. The free plan's $5 a month covers about 2,500 |

### 🔍 What SEC EDGAR Scraper does

In `search` mode it asks EDGAR's full-text index for your phrase and pages through the hits. Your
words go in as one quoted phrase, so `artificial intelligence` finds that pair of words together, not
documents that happen to contain both somewhere. There are no boolean operators and no wildcards.

In `company` mode you hand it tickers, CIKs or a mix of the two, and it reads each company's filing
history, newest first, as far back as your limit or your dates need.

Both modes take the same form filter and the same date window, and both stop at the same run total.
What you get is filing metadata plus `filingUrl`, which points at the document itself rather than a
landing page, so you can hand it straight to whatever reads it next.

### 📋 What data you get from each SEC filing

| What you get | Field |
|---|---|
| The form type | `form` |
| The company, its CIK and its ticker | `companyName`, `cik`, `ticker` |
| When it was filed, and the period it covers | `filingDate`, `reportDate` |
| The SEC's id for the filing | `accessionNumber` |
| The document that matched, and the SEC's label for it | `primaryDocument`, `description` |
| A direct link to the document | `filingUrl` |

### ▶️ How to scrape SEC EDGAR

1. Open [SEC EDGAR Scraper](https://apify.com/dami_studio/sec-edgar-scraper) and click
   **Try for free**.
2. Leave **Mode** on full-text search and type a phrase into **Search query**, or switch to company
   filings and fill in **Tickers or CIKs**.
3. Set **Max filings**. Start around 50 to see the row shape.
4. Narrow it with **Form types** and the two date fields if you want, then click **Start**.
5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.

### 💰 How much does it cost to scrape SEC EDGAR?

**$2.00 per 1,000 filings** on the Free plan. Paid plans pay a little less: $1.98 on Starter, $1.96 on Scale and $1.94 on Business. On the free plan, the $5
Apify gives you each month covers about 2,500 filings.

You pay per row delivered. Duplicate documents are dropped before they are counted, diagnostic rows
are not charged, and a search that matches nothing is not charged. Set a maximum cost on the run and
it stops when it gets there.

### 📥 What you give it

```json
{
  "mode": "search",
  "query": "artificial intelligence",
  "forms": "10-K,8-K",
  "startDate": "2024-01-01",
  "maxItems": 500
}
```

```json
{
  "mode": "company",
  "tickers": ["AAPL", "TSLA", "0000320193"],
  "forms": "10-K",
  "maxItems": 200
}
```

| Field | Default | What it is |
|---|---|---|
| `mode` | `search` | `search` for the full-text index, `company` for filing histories. Anything else is treated as `search`. |
| `query` | none, the form starts with `artificial intelligence` | The phrase to search for. Needed in `search` mode, ignored in `company` mode. |
| `tickers` | empty | Tickers like `AAPL`, or numeric CIKs, mixed freely. Needed in `company` mode, ignored in `search` mode. |
| `forms` | empty | Comma-separated form types, such as `10-K,8-K`. Empty means every form. Works in both modes. In `company` mode the match is exact, so `10-K` does not pick up `10-K/A`. |
| `startDate` | empty | `YYYY-MM-DD`. Only filings filed on or after this date. Works with or without `endDate`. |
| `endDate` | empty | `YYYY-MM-DD`. Only filings filed on or before this date. Works with or without `startDate`. |
| `maxItems` | `100` | The total for the whole run, up to 10,000. Not a per-company figure. |
| `notionConnector` | none | Optional. Writes each row into your Notion once the run finishes. |
| `notionParentId` | none | Optional. The Notion data source to write into. |
| `proxyConfiguration` | off | Optional network settings. Off by default, and a normal run does not need it. |

**`maxItems` is a budget for the run, shared by every ticker in the list.** Four tickers at
`maxItems: 100` does not give you 100 each. The first company can spend the whole budget before the
fourth is reached, so put the ones you care about first.

### 📤 What you get back

A real row from a run on 3 October 2026, for `artificial intelligence`:

```json
{
  "ok": true,
  "form": "20-F",
  "companyName": "Xiao-I Corp",
  "cik": "0001935172",
  "ticker": "AIXI",
  "filingDate": "2023-04-28",
  "reportDate": "2022-12-31",
  "accessionNumber": "0001213900-23-033683",
  "primaryDocument": "f20f2022ex4-19_xiaoicorp.htm",
  "description": "ENGLISH TRANSLATION OF AI CLOUD PLATFORM SERVICE CONTRACT BETWEEN SHANGHAI XIAO-I ROBOT TECHNOLOGY CO., LTD. AND CUSTOMER F DATED JUNE 27, 2022",
  "filingUrl": "https://www.sec.gov/Archives/edgar/data/1935172/000121390023033683/f20f2022ex4-19_xiaoicorp.htm"
}
```

| Field | How to read it |
|---|---|
| `form` | The form type, such as `10-K`, `8-K` or `20-F`. |
| `cik` | The SEC's company number, zero-padded to ten digits. Stable, unlike a ticker. |
| `ticker` | `null` when the SEC lists no ticker for the company, as with most funds. |
| `reportDate` | The period the filing covers, which is not the date it was filed. `null` on forms that cover no period, such as a 497K or a 424B2. |
| `accessionNumber` | The SEC's id for the filing. Pair it with `primaryDocument` to dedupe across runs. |
| `primaryDocument` | The file inside the filing that matched. The row above is an exhibit, not the 20-F itself. |
| `description` | The SEC's own label for that document, when it gives one. |
| `filingUrl` | Direct link to the document, or to the filing's text file on an old filing with no separate document. |

### 🧾 Reading the output

Two kinds of row land in your dataset, and `ok` tells them apart.

| Row | How to spot it | Billed |
|---|---|---|
| A filing | `ok: true` and an `accessionNumber` | yes |
| A diagnostic | `ok: false` and an `errorCode` | no |

The overview table in the Apify Console shows the filing columns only, so a diagnostic row looks
blank there. Switch to the JSON or All fields view to read it.

| Code | What it means |
|---|---|
| `BAD_INPUT` | `search` mode with no query, `company` mode with no tickers, or a date not written `YYYY-MM-DD`. The row says which. |
| `NO_RESULTS` | The request worked and nothing matched your phrase, forms or dates. |
| `NOT_FOUND` | Some tickers or CIKs did not resolve. The `unresolved` field lists them, and the companies that did resolve still returned rows. |
| `RATE_LIMITED` | The SEC asked for a slower pace than the run could keep. |
| `SERVER_ERROR` | The SEC answered with a server error. Usually passes. |
| `NOT_SERVED` | This filing was not served this run. Re-run it later. Runs before 13 October 2026 wrote `BLOCKED` here, and runs from 13 to 17 October wrote `NETWORK`. |
| `NETWORK` | The SEC was unreachable. Re-run it. |
| `TIME_LIMIT` | The run got close to its time limit and stopped on its own. The filings delivered before that are charged as usual. Give the run more time, or ask for fewer filings, to get the rest. |
| `UNEXPECTED_ERROR` | The run stopped early on an unexpected error. The results before this row are kept. |

A run that ends on one of these rows still finishes as succeeded, including when the time limit
stopped it before any filing came back: the `TIME_LIMIT` row and an amber status message say so.

### 💡 What people use it for

- Finding companies that used a phrase in their filings, then reading the documents that came back.
- Pulling one company's 10-K and 8-K history for a model that needs the source text, not a summary.
- Watching a form type on a schedule, using the date fields so each run only picks up what is new.
- Building a CIK list for an internal database, since the CIK survives ticker changes and renames.

### 🚧 What it does not do

- **Metadata and a link, never the text.** The filing itself is not downloaded or parsed here.
- **Full-text search stops at 10,000 results per query.** That is the SEC's ceiling. Narrow it with a form filter or a date range.
- **One row per matching document.** A filing with several matching exhibits produces several rows.
- **The query is one exact phrase.** Quotes of your own, `AND`, `OR` and wildcards are not
  interpreted.
- **A ticker that has been reused** resolves to whichever company holds it today. Use a CIK to be
  certain.
- It is not an official SEC EDGAR tool. Dami's Studio is independent and is not affiliated with or endorsed by SEC EDGAR or the SEC, or by any other company named on this page.

### 🧭 Which market data scraper do you need?

| If you want | Use |
|---|---|
| Coin prices, market caps and rankings | [CoinGecko Scraper](https://apify.com/dami_studio/coingecko-scraper) |
| Price, liquidity and volume of a DEX trading pair | [DexScreener Pair Price & Liquidity Scraper](https://apify.com/dami_studio/dexscreener-pairs-scraper) |
| The daily Crypto Fear and Greed reading, back to 2018 | [Crypto Fear and Greed Index Scraper](https://apify.com/dami_studio/crypto-fear-greed-scraper) |
| Large Polymarket trades and the wallets behind them | [Polymarket Whale Tracker](https://apify.com/dami_studio/polymarket-whale-tracker) |
| Company filings by keyword, ticker or CIK | This one |
| Indian mutual fund NAVs, today's or back to 2010 | [Indian Mutual Fund NAV Scraper](https://apify.com/dami_studio/mutual-fund-nav-scraper) |

### ❓ Questions people ask

#### Do I need an SEC account or key?

No. EDGAR is a public government system and nothing here needs an account.

#### Why did four tickers give me fewer rows than I expected?

`maxItems` is one budget for the whole run. Raise it, or run the companies separately.

#### Why is the ticker empty on some rows?

The SEC lists no ticker for that company, as with most funds. The `cik` is the one to keep.

#### Can I search for two phrases at once?

Not in one run. The query goes in as a single quoted phrase. Run them separately and join on
`accessionNumber`.

#### How do I pick up only new filings on a schedule?

Set `startDate` to the day you last ran it, and each run picks up what has been filed since.

#### Can I call it from code or connect it to an AI assistant?

The [API tab](https://apify.com/dami_studio/sec-edgar-scraper/api/python) has code for Python, JavaScript and the CLI.
MCP clients like Claude and ChatGPT use
`https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/sec-edgar-scraper`; coding assistants can load [our
skill file](https://api.apify.com/v2/key-value-stores/BTBHU3DdiuoF4JOsK/records/apify-us-public-records-SKILL.md). All
three bill your Apify account at the same price.

#### Is scraping SEC EDGAR legal?

EDGAR is the SEC's public filing database, and these are documents companies are required by law
to file. Apify's write-up on [the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/)
is a good starting point, and we are not lawyers.

### 🆘 If something breaks

Open the **Issues** tab on the actor page. Send the run ID and the input you used. The `errorCode` on
the diagnostic row usually names the problem on its own.

# Actor input Schema

## `mode` (type: `string`):

How to find filings. "search" runs an EDGAR full-text search across all filings using your query. "company" pulls a company's filing history by ticker or CIK.

## `query` (type: `string`):

Full-text query for "search" mode (e.g. "artificial intelligence"). Matched as a phrase across filing documents. Required when mode is "search"; ignored in "company" mode. Note: SEC's full-text index is sparse, "search" rows often have null ticker, reportDate, and description (see README). Use "company" mode for more complete records.

## `forms` (type: `string`):

Comma-separated SEC form types to filter by, e.g. "10-K,8-K". Leave empty for all forms. Applies to both modes.

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

For "company" mode: one or more stock tickers (e.g. AAPL, TSLA) or numeric CIKs. Each company's filing history is fetched. Ignored in "search" mode.

## `endDate` (type: `string`):

Only include filings filed on or before this date (YYYY-MM-DD). Optional.

## `startDate` (type: `string`):

Only include filings filed on or after this date (YYYY-MM-DD). Optional.

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

Maximum number of filings to return across the WHOLE run (a total budget shared by all companies/queries, not a per-company cap). In "company" mode the run stops once this total is hit, so earlier tickers in the list can consume the budget before later ones. Full-text search itself caps at 10000 results.

## `notionConnector` (type: `string`):

Optional. Write each item as a page into your Notion when the run finishes. Authorize a Notion connector once in Settings → API & Integrations → MCP connectors, then pick it here. Leave empty to skip (default), results are always saved to the dataset regardless.

## `notionParentId` (type: `string`):

Optional. The Notion data source ID of the database to write into (only used if a Notion connector is set). Leave empty to create the pages privately in your workspace instead.

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

Optional, and not needed for a normal run. Your own proxy servers are used exactly as given.

## Actor input object example

```json
{
  "mode": "search",
  "query": "artificial intelligence",
  "forms": "",
  "tickers": [],
  "endDate": "",
  "startDate": "",
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Scraped rows are stored in the default dataset (one row per result). Blocked/empty/error runs return a single uncharged diagnostic row instead.

# 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 = {
    "query": "artificial intelligence"
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/sec-edgar-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 = { "query": "artificial intelligence" }

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/sec-edgar-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 '{
  "query": "artificial intelligence"
}' |
apify call dami_studio/sec-edgar-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/sec-edgar-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/e1F6O4dqb7RKDYkb4/builds/sLdVLKyccOXTWI71L/openapi.json
