# SEC EDGAR Filings & XBRL Financials Scraper (`signalclear/sec-edgar-scraper`) Actor

10-K, 10-Q, 8-K, DEF 14A and other SEC filings plus XBRL financials (revenue, net income, EPS, assets) from the official SEC EDGAR APIs. Tickers, CIKs or names; optional full-text search and document text. Rate-limited; failed companies never charged.

- **URL**: https://apify.com/signalclear/sec-edgar-scraper.md
- **Developed by:** [signal clear](https://apify.com/signalclear) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 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.

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 Filings & XBRL Financials Scraper

Get SEC filings (10-K, 10-Q, 8-K, DEF 14A, S-1, 13F-HR, Form 4 and any other form type) and a clean XBRL financials summary (revenue, net income, EPS, total assets, total liabilities, shares outstanding) for any US-listed company. Data comes straight from the SEC's official public EDGAR APIs. There is no HTML scraping, no API key and no login.

- **Official source.** It reads `data.sec.gov`, `efts.sec.gov` (EDGAR full-text search) and the EDGAR archives. These are the same APIs the SEC publishes for developers.
- **Bounded and polite.** All requests go through one limiter at 8 requests per second, below the SEC's limit of 10. Every request has a timeout, rate limiting gets a few short waits, and each company has a capped number of attempts.
- **Failed companies are never charged.** A company's rows are saved only after the whole company succeeds. If it fails (for example an unknown ticker, or the SEC stays unavailable), nothing from it reaches the dataset, and the failure is listed in the `FAILED_COMPANIES` record.
- **Built for filing season.** 10-K season runs January to March, and proxy season (DEF 14A) runs March to May. You can pull every new annual report or proxy statement for a watch list, or full-text search all filers for a phrase.

### What you can do

| Goal | Input |
|---|---|
| Latest 10-K, 10-Q and 8-K filings for a watch list | `companies: ["AAPL", "MSFT", "NVDA"]` |
| This year's proxy statements | `forms: ["DEF 14A"]`, `filedSince: "2027-01-01"` |
| Quarterly and annual financials for a set of tickers | `includeCompanyFacts: true`, `maxFilingsPerCompany: 0` |
| Every 10-K that mentions a phrase | `fullTextQuery: "\"tariff\""`, `forms: ["10-K"]`, no companies |
| A company's filings that mention a phrase | `companies` plus `fullTextQuery` |
| Filing text for NLP or an LLM | `includeDocumentText: true` |

### Input

| Field | Default | Notes |
|---|---|---|
| `companies` | | Tickers (`AAPL`, `BRK.B`), CIKs (`320193` or `0000320193`) or company names (exact, or a unique prefix). A filer without a ticker, such as a fund or a private issuer, needs its CIK. An unknown ticker or CIK fails at once, with no retries. |
| `forms` | `10-K, 10-Q, 8-K` | Any SEC form type. Leave it empty for every form. |
| `includeAmendments` | `true` | Also return `/A` amendments of the chosen forms. |
| `filedSince` / `filedUntil` | | Filing date range, `YYYY-MM-DD`. |
| `fullTextQuery` | | EDGAR full-text search (filings since 2001). Use quotes for an exact phrase. With companies, only their matching filings are returned. Without companies, the filers that match become the companies. Each filing row lists the documents that matched in `fullTextHits`. |
| `maxFilingsPerCompany` | `50` | Newest first. Set `0` to get only facts rows. |
| `includeCompanyFacts` | `false` | Adds up to 4 facts rows per company, one for each of its latest fiscal periods (10-K or 10-Q). Each facts row is billed as a result. |
| `concepts` | | Extra XBRL concepts for the facts rows, such as `OperatingIncomeLoss`, `StockholdersEquity` or `dei:EntityPublicFloat`. Names without a prefix are `us-gaap`. |
| `includeDocumentText` | `false` | Downloads each filing's primary document and returns it as plain text. It costs one extra request per filing. |
| `maxDocumentTextChars` | `200000` | Text is cut at this length. A full 10-K is often 300,000 to 600,000 characters. |
| `maxItems` | `1000` | Total row cap (filings plus facts). |
| `userAgentContact` | placeholder | **Set this to your own name and email.** See below. |
| `maxConcurrency` | `2` | Companies processed in parallel. The limiter caps the total rate either way. |
| `maxAttempts` | `3` (max 5) | Attempts per company on rate limiting, server errors or timeouts. Data already fetched is kept between attempts. |
| `requestTimeoutSecs` | `30` | Timeout for each request. |
| `proxyConfiguration` | Apify Proxy on | The SEC identifies tools by User-Agent, not by IP, so datacenter proxies work. Turn the proxy off to connect directly. |

#### Set your own `userAgentContact`

The [SEC fair-access policy](https://www.sec.gov/os/accessing-edgar-data) asks every automated tool to declare who is making the requests, with a contact email, in the User-Agent header. The Actor sends `signalclear-edgar-actor/0.1 <your userAgentContact>`. Put your name or company and an email there, for example `Jane Doe jane@example.com`. The default is a placeholder, and the run log warns you while it is still set. The value goes only to sec.gov.

### Output

Each dataset row has a `type`: `filing` or `facts`. The dataset has two views, **Filings** and **XBRL financials**.

#### Filing row

```json
{
  "type": "filing",
  "cik": "0000320193",
  "ticker": "AAPL",
  "companyName": "Apple Inc.",
  "accessionNumber": "0000320193-26-000020",
  "form": "10-Q",
  "filedAt": "2026-07-31",
  "acceptedAt": "2026-07-31T10:01:02.000Z",
  "reportDate": "2026-06-27",
  "periodOfReport": "2026-06-27",
  "primaryDocument": "aapl-20260627.htm",
  "primaryDocDescription": "10-Q",
  "primaryDocUrl": "https://www.sec.gov/Archives/edgar/data/320193/000032019326000020/aapl-20260627.htm",
  "indexUrl": "https://www.sec.gov/Archives/edgar/data/320193/000032019326000020/0000320193-26-000020-index.htm",
  "items": [],
  "size": 5946811,
  "isXBRL": true,
  "isInlineXBRL": true,
  "fileNumber": "001-36743",
  "input": "AAPL",
  "scrapedAt": "2026-10-28T20:12:06.446342+00:00"
}
```

- `items` holds the 8-K item numbers, for example `["2.02", "9.01"]` for an earnings release.
- `fullTextHits` appears only when `fullTextQuery` is set.
- `documentText`, `documentTextChars` and `documentTextTruncated` appear when `includeDocumentText` is on. If the primary document is missing or is not text (for example a PDF), `documentText` is `null` and `documentTextError` explains why.

#### Facts row

```json
{
  "type": "facts",
  "cik": "0000320193",
  "ticker": "AAPL",
  "companyName": "Apple Inc.",
  "fiscalYear": 2025,
  "fiscalPeriod": "FY",
  "form": "10-K",
  "accessionNumber": "0000320193-25-000079",
  "filedAt": "2025-10-31",
  "periodEnd": "2025-09-27",
  "metrics": {
    "revenue": 416161000000,
    "netIncome": 112010000000,
    "epsBasic": 7.49,
    "epsDiluted": 7.46,
    "totalAssets": 359241000000,
    "totalLiabilities": 285508000000,
    "sharesOutstanding": 14776353000,
    "OperatingIncomeLoss": 133050000000
  },
  "units": { "revenue": "USD", "epsBasic": "USD/shares", "sharesOutstanding": "shares" }
}
```

How the facts rows are built:

- Each row shows the values that one 10-K or 10-Q reported for its own period. `FY` rows hold 12-month figures. Quarterly rows (`Q1` to `Q3`) hold the 3-month figures, not year-to-date. Assets and liabilities are as of `periodEnd`.
- `revenue` uses the first of these concepts that the filing reported: `RevenueFromContractWithCustomerExcludingAssessedTax`, `Revenues`, `SalesRevenueNet`, then the variants that include assessed tax or are net of interest expense.
- `sharesOutstanding` is the cover-page figure (`dei:EntityCommonStockSharesOutstanding`), which is usually dated a few weeks after `periodEnd`.
- A metric the company did not report for a period is left out. Nothing is estimated.
- Values are as reported. Fiscal years follow the company's own calendar, so Microsoft's fiscal 2027 Q1 ends in September 2026.

### Limits

- **The SEC rate limit is 10 requests per second for each requester.** The Actor stays at 8 per second, which is about 28,000 requests an hour. One company with filings and facts takes 2 to 3 requests. Document text adds one request per filing.
- **XBRL facts exist only for filers that submit XBRL**, which means operating companies filing 10-K and 10-Q since about 2009 to 2011. Funds, most foreign private issuers (20-F filers report in IFRS, not us-gaap) and shell or very old filers return no facts rows. The run log then notes "no XBRL financial data", and the company still succeeds.
- Full-text search covers filings since 2001. It returns at most 10,000 matching documents per query, and at most 1,000 per company.
- Name lookup uses the SEC ticker list, about 10,000 current listed filers. Delisted companies and companies without a ticker need their CIK.
- Primary documents are downloaded up to 20 MB, and their text is cut at `maxDocumentTextChars`.

### Pricing

The Actor is pay per result. Every saved row, whether a filing or a facts row, is one result. Failed companies, and the `FAILED_COMPANIES` record, cost nothing. Turning on `includeDocumentText` does not change the price per row, but the rows get much larger (about 50 KB at the default text cap, compared with under 1 KB without text).

### Legal

The Actor returns US government public records that the SEC publishes for free public access. It collects no personal data beyond what the filings themselves publish. For example, Form 3, 4 and 5 insider filings name the reporting officers and directors, and the Actor returns those forms only when you add them to `forms`. You are responsible for following the SEC's fair-access policy, which is why you should set `userAgentContact`, and for how you use the data. This Actor is not affiliated with or endorsed by the U.S. Securities and Exchange Commission.

### Failed companies

When the run ends, the default key-value store holds `FAILED_COMPANIES`, a list of `{company, cik, error, attempts}`. An `attempts` value of `0` means the input was never sent to the SEC, for example an unknown ticker. The run succeeds when at least one company succeeds, and it fails only when every company failed. In that case nothing was saved or charged.

# Actor input Schema

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

One company per line: a ticker (AAPL, BRK.B), a CIK (320193 or 0000320193) or a company name (exact or a unique prefix, e.g. Microsoft). Filers without a ticker need their CIK. Leave empty to let the full-text query pick the companies.

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

SEC form types to return, e.g. 10-K, 10-Q, 8-K, DEF 14A, S-1, 13F-HR, 4, 20-F. Leave empty for every form type. Form 4 (insider transactions) names the reporting officers and directors.

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

Also return amended filings (10-K/A, 8-K/A ...) for the chosen form types.

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

Only filings filed on or after this date (YYYY-MM-DD). Leave empty for no lower bound.

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

Only filings filed on or before this date (YYYY-MM-DD). Leave empty for no upper bound.

## `fullTextQuery` (type: `string`):

Optional EDGAR full-text search (filings since 2001). Use quotes for a phrase, e.g. "artificial intelligence". With companies, only their filings that match are returned; without companies, the matching filers become the companies. Each filing lists the documents that matched in fullTextHits.

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

Newest filings first. Set 0 to return only XBRL facts rows.

## `includeCompanyFacts` (type: `boolean`):

Adds up to 4 facts rows per company, one per latest fiscal period (10-K/10-Q): revenue, net income, basic and diluted EPS, total assets, total liabilities and shares outstanding where the company reported them in XBRL. One extra request per company. Each facts row is billed as a result.

## `concepts` (type: `array`):

Optional us-gaap concept names to add to the facts rows, e.g. OperatingIncomeLoss, StockholdersEquity, NetCashProvidedByUsedInOperatingActivities. Prefix another taxonomy with a colon, e.g. dei:EntityPublicFloat. Concepts a company never reported are left out.

## `includeDocumentText` (type: `boolean`):

Download each filing's primary document and add its plain text (HTML stripped, inline XBRL header removed). One extra request per filing; PDFs and images are skipped.

## `maxDocumentTextChars` (type: `integer`):

Cut the document text after this many characters (documentTextTruncated is then true). A full 10-K is often 300,000 to 600,000 characters.

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

Stop after this many dataset rows in total (filings plus facts rows).

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

The SEC fair-access policy asks automated tools to identify who is making requests: put your name or company and an email address here, e.g. "Jane Doe jane@example.com". It is sent only to sec.gov in the User-Agent header.

## `maxConcurrency` (type: `integer`):

How many companies are processed at once. All requests share one limiter at 8 per second, under the SEC limit of 10.

## `maxAttempts` (type: `integer`):

How many times a company is retried after rate limiting, server errors or timeouts before it is reported as failed. Work already fetched is kept between attempts.

## `requestTimeoutSecs` (type: `integer`):

Timeout for each request to the SEC.

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

The SEC identifies tools by User-Agent, not IP, so a datacenter proxy is fine. Turn Apify Proxy off to connect directly.

## Actor input object example

```json
{
  "companies": [
    "AAPL",
    "MSFT"
  ],
  "forms": [
    "10-K",
    "10-Q",
    "8-K"
  ],
  "includeAmendments": true,
  "maxFilingsPerCompany": 50,
  "includeCompanyFacts": false,
  "includeDocumentText": false,
  "maxDocumentTextChars": 200000,
  "maxItems": 1000,
  "userAgentContact": "Your Name your-email@example.com",
  "maxConcurrency": 2,
  "maxAttempts": 3,
  "requestTimeoutSecs": 30,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `filings` (type: `string`):

Dataset results in the "Filings" view.

## `facts` (type: `string`):

Dataset results in the "XBRL financials (facts rows)" view.

## `failed` (type: `string`):

JSON list of companies that failed after every retry, with the error for each. Empty when everything succeeded. Failed inputs are never charged.

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

// Run the Actor and wait for it to finish
const run = await client.actor("signalclear/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 = {
    "companies": [
        "AAPL",
        "MSFT",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("signalclear/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 '{
  "companies": [
    "AAPL",
    "MSFT"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call signalclear/sec-edgar-scraper --silent --output-dataset

```

## MCP server setup

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