# SEC EDGAR Filings Scraper & API - 10-K, 10-Q, 8-K by Ticker (`neverempty/sec-edgar-filings`) Actor

For equity research, fintech products and compliance teams: company filings from the SEC's own EDGAR API by ticker or CIK, with the full history and not just the recent window. EDGAR keeps about 1,000 filings in its main response - for Apple that hides 1,246 of 2,246 filings, 55.5% of the history.

- **URL**: https://apify.com/neverempty/sec-edgar-filings.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Developer tools, MCP servers, Automation
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.11 / 1,000 filing returneds

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?

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

## SEC EDGAR Filings Scraper & API

**For equity research, competitive intelligence, compliance monitoring and filing-driven alerts**: company filings from the SEC's own EDGAR API, by ticker or CIK, as flat rows. No API key, no scraping, no proxy.

**Stop at EDGAR's main response and you lose most of the history.** EDGAR puts about the newest **1,000** filings in `filings.recent` and everything older in separate files, and **nothing marks the cut**. Measured against the live API on 2026-09-10 for Apple (CIK 320193): **1,000** filings in `filings.recent` back to 2015-07-22, and **1,246** more in the older file from 1994-01-26 to 2015-07-20 — **1,246 of 2,246, or 55.5% of the history, missing** if you stop there. (It is not exactly 1,000 every time either: Apple returns 1,000, Cheniere Energy 1,007.) One switch reads the older files too.

**The form filter is applied before the row limit**, so asking for 100 10-K filings gives you up to 100 10-K filings — not whatever 10-Ks happen to fall inside the first 100 rows. That matters because of how lopsided the mix is: of Apple's 1,000 most recent filings, **589 are Form 4** insider transactions and only **34 are 10-Q**.

**Tickers are messier than they look, and this Actor handles it.** The SEC writes `BRK-B`, `UHAL-B`, `BF-B` — **544 tickers contain a hyphen** — and its own list holds **10,407 tickers for 8,013 companies**, because 1,441 companies have more than one. `AAPL` and `320193` are the same company, so naming both collects it once rather than charging you twice. An unresolvable ticker, a CIK EDGAR answers 404 for, and a run where the SEC's ticker list itself could not be read each come back as their own row with the reason — never as "no filings".

Export as JSON, CSV or Excel.

```json
{
  "companies": ["AAPL", "MSFT", "BRK.B"],
  "forms": ["10-K", "10-Q", "8-K"],
  "includeFullHistory": true
}
```

### What this fixes about the raw API

Everything below was measured against the live API on 2026-09-10, not read from documentation.

#### 1. The main response holds only the most recent 1,000 filings

EDGAR puts about the newest 1,000 filings in `filings.recent` and everything older in separate files listed
under `filings.files`. Nothing marks the cut. (It is not exactly 1,000 every time - Apple returns 1,000,
Cheniere Energy returns 1,007 - so counting on the number is a mistake too.) Read only the main response and you get a table that looks complete and
is not.

| | Apple (CIK 320193) |
|---|---|
| In `filings.recent` | 1,000 filings, back to 2015-07-22 |
| In the older file | 1,246 filings, 1994-01-26 to 2015-07-20 |
| **Missing if you stop at `recent`** | **1,246 of 2,246 - 55.5% of the history** |

Turn on `includeFullHistory` and the older files are read too. Every row carries `filingSource`, which says
whether it came from the recent block or from a named older file, so the split can be checked rather than
trusted.

#### 2. Share classes are written with a hyphen, and the same company can be named twice

The SEC's list writes `BRK-B`, `UHAL-B`, `BF-B` - **544 tickers contain a hyphen and exactly one contains a
dot** - while every finance interface people actually use writes `BRK.B`. A dot is accepted here and converted,
so the form you type is not the reason a company comes back as unknown.

And `AAPL` and `320193` are the same company. Naming both collects it once: the resolved CIK is remembered, and
the second mention is skipped rather than fetched and charged again.

#### 3. Tickers and companies are not one to one

The SEC's own list holds **10,407 tickers for 8,013 companies**: 1,441 companies have more than one, because
share classes get their own symbol (UHAL and UHAL-B, AEM and AEMRF). Counting tickers as companies overstates
by about 30 per cent. Every row carries `tickers` as an array of all symbols the SEC maps to that CIK, not just
the one you asked for.

#### 4. Form 4 drowns everything else

Of Apple's 1,000 most recent filings, **589 are Form 4** insider transactions and only **34 are 10-Q**. A form
filter is not a nicety here. `forms` matches the form type exactly and case-insensitively, and the row limit is
applied **after** filtering, so asking for 100 10-K filings gives you up to 100 10-K filings rather than
whatever 10-Ks happen to fall inside the first 100 rows.

#### 5. A ticker the SEC does not list is not a company without filings

An unresolvable ticker, a CIK EDGAR answers 404 for, a run where the SEC's ticker list itself could not be read,
and a request that simply failed each come back as their own row that says which of the four happened. The
ticker-list failure gets its own wording, because saying "that ticker is not in the SEC's list" when the list
was never read is a false claim about the SEC. None of them is charged, and none of them is reported as "no
filings". The 404 body is XML rather than JSON, which is a common way for a JSON-only reader to crash.

### What you get

One row per filing: `companyName`, `cik`, `tickers`, `exchanges`, `sicCode`, `sicDescription`,
`stateOfIncorporation`, `fiscalYearEnd`, then `form`, `filingDate`, `reportDate`, `acceptanceDateTime`, `act`,
`fileNumber`, `items`, `accessionNumber`, `primaryDocument`, `primaryDocDescription`, `sizeBytes`, `isXBRL`,
`isInlineXBRL`, `filingSource`, and two working links - `documentUrl` to the filing itself and
`filingIndexUrl` to its folder.

The folder name in those URLs is the accession number with its hyphens removed. Leaving them in returns 404 for
every row, which is the sort of thing that is easy to ship and hard to notice.

### Input

| Field | What it does |
|---|---|
| `companies` | Tickers such as `AAPL`, or CIK numbers such as `320193`. CIKs work for companies with no ticker. With the whole input empty, the example companies `AAPL` and `MSFT` are used and every row says so in `note`. Form types or dates without a company return one unpaid `bad-input` row instead. |
| `forms` | Form types to keep - `10-K`, `10-Q`, `8-K`, `DEF 14A`, `4`, `13F-HR`. Empty or left out means every form: no form type is added on your behalf. |
| `includeFullHistory` | **Off by default.** Turn it on to read the older filing files as well as the recent block - one extra request per file. Without it you get the recent block only, which for Apple is everything back to 2015 - except that when `filedSince` or `filedUntil` reaches back before the recent block, the older files covering those dates are read anyway, so a date range is never cut short silently. That matters for banks: JPMorgan's recent block covers only about a year. |
| `filedSince` / `filedUntil` | Date bounds such as `2024-01-01`. Filings with no readable date are excluded when set. |
| `maxFilingsPerCompany` | Row limit per company, applied after filtering. You are charged only for rows you receive. |
| `maxRetries` | Attempts per request. HTTP 404 is permanent and is never retried. |

Requests are paced to stay inside the SEC's published limit of ten per second, and every request identifies
itself with a contact address as the SEC's access policy asks.

### Source and licence

SEC EDGAR submissions API (`data.sec.gov`) and the SEC company ticker list (`www.sec.gov`). Works of the US
federal government are in the public domain. This Actor makes plain HTTPS requests to the documented JSON
endpoints; it does not scrape any web page and needs no API key or proxy.

# Actor input Schema

## `companies` (type: `array`):

Tickers such as AAPL, or CIK numbers such as 320193. Tickers are resolved through the SEC's own company\_tickers.json, which holds 10,407 tickers for 8,013 companies. The SEC writes share classes with a hyphen (BRK-B); a dot (BRK.A) is accepted here and converted. A ticker it does not list comes back as its own row saying so, never as a company with no filings. Naming the same company twice - once by ticker and once by CIK - collects it once, so you are never charged twice for the same filings. CIK numbers work for companies with no ticker at all. Leave the whole input empty and the example companies AAPL and MSFT are used; every row then says so in its note. If you set form types or dates but no company, one unpaid row asks for a company instead of charging you for the example.

## `forms` (type: `array`):

Keep only these form types, matched exactly and case-insensitively: 10-K, 10-Q, 8-K, DEF 14A, S-1, 4, 13F-HR and so on. Leave empty for every form. This matters more than it looks: of Apple's most recent 1,000 filings, 589 are Form 4 insider transactions and only 34 are 10-Q.

## `includeFullHistory` (type: `boolean`):

EDGAR puts only the most recent 1,000 filings in the main response and the rest in separate files. Off, you get the recent block alone - for Apple that is everything back to 2015 and misses 1,246 older filings, 55 per cent of its history. On, the older files are read too, which costs one extra request per file. When you set filedSince or filedUntil and those dates reach back before the recent block, the older files covering those dates are read automatically even with this off - so a date range is never cut short silently. Banks such as JPMorgan keep only about a year in the recent block.

## `filedSince` (type: `string`):

A date such as 2024-01-01. Filings with no readable filing date are excluded when this is set, so the result never implies a date the source did not give.

## `filedUntil` (type: `string`):

A date such as 2024-12-31.

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

Upper limit of rows kept per company, applied after the form and date filters rather than before, so asking for 100 10-K filings gives you up to 100 10-K filings. You are charged for the rows you actually receive.

## `maxRetries` (type: `integer`):

How many times to try a request in total when EDGAR does not answer. HTTP 404 is a permanent answer and is never retried. Requests are paced to stay inside the SEC's published limit of ten per second.

## Actor input object example

```json
{
  "companies": [
    "AAPL",
    "MSFT"
  ],
  "forms": [
    "10-K",
    "10-Q",
    "8-K"
  ],
  "includeFullHistory": false,
  "filedSince": "",
  "filedUntil": "",
  "maxFilingsPerCompany": 100,
  "maxRetries": 4
}
```

# Actor output Schema

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

One row per SEC EDGAR filing, plus one row for each company whose ticker could not be resolved, whose CIK EDGAR does not hold, or that could not be read.

# 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 = {
    "companies": [
        "AAPL",
        "MSFT"
    ],
    "forms": [
        "10-K",
        "10-Q",
        "8-K"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/sec-edgar-filings").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 = {
    "companies": [
        "AAPL",
        "MSFT",
    ],
    "forms": [
        "10-K",
        "10-Q",
        "8-K",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/sec-edgar-filings").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 '{
  "companies": [
    "AAPL",
    "MSFT"
  ],
  "forms": [
    "10-K",
    "10-Q",
    "8-K"
  ]
}' |
apify call neverempty/sec-edgar-filings --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/sec-edgar-filings"
        }
    }
}
```

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/Vm7i4UQ58BG0KlYM0/builds/PQpUTdz7Tfn0kln5A/openapi.json
