# SEC EDGAR Filings Full-Text Search (`xtracto/sec-edgar-filings-search`) Actor

Search the full text of every SEC EDGAR filing: form type, company names and tickers, CIKs, filing and period dates, SIC codes, states, and direct links to the filing documents. Keyless public API, no login.

- **URL**: https://apify.com/xtracto/sec-edgar-filings-search.md
- **Developed by:** [Farhan Febrian Nauval](https://apify.com/xtracto) (community)
- **Categories:** Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.67 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Filings Full-Text Search

Search the full text of every SEC EDGAR filing and get structured results: form type, company
names and tickers, CIKs, filing and period dates, 8-K item codes, SIC codes, incorporation and
business states, and direct links to the filing documents.

Keyless public government API. No login, no browser, **no proxy needed**.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `searchQueries` | array | *required* | One search per entry. `"climate risk"` in double quotes matches the exact phrase |
| `forms` | array | — | `10-K`, `8-K`, `S-1`, `DEF 14A`, … |
| `ciks` | array | — | Zero-padded ten-digit CIKs, e.g. `0000320193` |
| `filedFrom` / `filedTo` | string | — | `YYYY-MM-DD`. Give either one and the actor fills the other — EDGAR ignores a half-open range |
| `locationCode` | string | — | Two-letter state/country of the filer's business address |
| `maxItemsPerQuery` | integer | `300` | Capped by the API at 10,000 |
| `userAgent` | string | actor id | See "Identifying yourself" below |

### Output

```jsonc
{
  "_input": "\"material definitive agreement\"",
  "_source": "S1-edgar-fts",
  "_scrapedAt": "2026-09-09T13:02:55Z",

  "accessionNumber": "0000035527-22-000119",
  "documentId": "0000035527-22-000119:fitbannualreport202110-k.pdf",
  "documentFile": "fitbannualreport202110-k.pdf",
  "documentUrl": "https://www.sec.gov/Archives/edgar/data/35527/000003552722000119/fitbannualreport202110-k.pdf",
  "filingIndexUrl": "https://www.sec.gov/Archives/edgar/data/35527/000003552722000119/",

  "form": "10-K", "rootForms": ["10-K"],
  "fileType": "10-K", "fileDescription": "ANNUAL REPORT",
  "filedAt": "2022-02-24", "periodEnding": "2021-12-31",
  "items": ["1.02", "9.01"],          // 8-K item codes; empty on other forms

  "ciks": ["0000035527"],
  "companyNames": ["FIFTH THIRD BANCORP"],
  "tickers": ["FITB", "FITBI", "FITBO", "FITBP"],
  "displayNames": ["FIFTH THIRD BANCORP (FITB, FITBI, FITBO, FITBP) (CIK 0000035527)"],
  "fileNumbers": ["001-31826"], "filmNumbers": ["25834114"],

  "sicCodes": ["6022"],
  "incorporationStates": ["OH"],
  "businessStates": ["OH"],
  "businessLocations": ["Cincinnati, OH"],

  "score": 12.4
}
```

### Four things worth knowing

**EDGAR reports failures inside a `200`.** Overrunning the result window returns HTTP 200 carrying
`{"errorType": "ResponseError", "errorMessage": "… Result window is too large …"}` — no `hits` key,
no error status. Code that checks only the status reads that as an empty page and stops, quietly,
having collected less than it should. This actor inspects the body and emits an `api_error` row.

**A single date bound is silently ignored.** `startdt` without `enddt` returns *exactly* the
unfiltered result set — same count, same first page, no error and no warning. Both bounds must be
present for the range to apply at all. This actor fills the missing side for you (today, or
2001-01-01 where full-text coverage begins) and says so in the log, so a one-sided range does what
you meant rather than quietly doing nothing.

**`total.relation` tells you whether the count is real.** EDGAR is honest about clamping: `eq` means
an exact count, `gte` means it stopped counting at 10,000 — and 10,000 is also the paging ceiling
(`from` tops out at 9900, since `from + 100` must not exceed it). The actor logs `1454 filings
match` versus `at least 10000 filings match` accordingly, and warns when you have asked for more
than can be served. Narrowing by form, date range or CIK is how you reach the rest.

**Company names carry their tickers, sometimes several.**
`FIFTH THIRD BANCORP (FITB, FITBI, FITBO, FITBP) (CIK 0000035527)` is one string upstream. The
names, tickers and CIKs ship separately, with the original in `displayNames`. Parentheses that are
part of a registered name — `SMART Modular Technologies (WWH), Inc.` — are left alone, because only
a *trailing* parenthesis is treated as a ticker group.

### Identifying yourself

SEC's fair-access policy asks automated requesters to identify themselves in the `User-Agent`, and
the default here names this actor rather than impersonating a browser. To be precise about what is
enforced versus what is asked: the server rejects only an **empty** User-Agent (403). Any non-empty
value is accepted. If you are running at volume, put your own name and contact in `userAgent`.

### Errors

| `_error` | Meaning |
|---|---|
| `invalid_input` | Empty search query |
| `no_results` | The search ran and matched no filings |
| `api_error` | A 200 carrying an error object — usually the result window is exhausted |
| `unexpected_shape` | A 200 without `hits`, or a hit without `_source` |
| `blocked` | Every TLS profile was refused |
| `network_error` | The ladder never reached the server |

If every query fails, the run itself fails rather than reporting success over an empty dataset.

# Actor input Schema

## `searchQueries` (type: `array`):

One full-text search per entry. Wrap a phrase in double quotes to match it exactly, e.g. "climate risk".

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

Filter by form, e.g. 10-K, 10-Q, 8-K, S-1, DEF 14A. Leave empty for all.

## `ciks` (type: `array`):

Filter to specific filers by CIK, e.g. 0000320193 for Apple. Ten-digit, zero-padded.

## `filedFrom` (type: `string`):

Earliest filing date, YYYY-MM-DD. Full-text search covers 2001 onward. EDGAR ignores a half-open range, so if you leave 'Filed to' empty the actor fills it with today.

## `filedTo` (type: `string`):

Latest filing date, YYYY-MM-DD. If you leave 'Filed from' empty the actor fills it with 2001-01-01 — EDGAR ignores a date range unless both bounds are present.

## `locationCode` (type: `string`):

Two-letter state or country code of the filer's business address, e.g. CA.

## `maxItemsPerQuery` (type: `integer`):

EDGAR serves at most 10,000 results per search however many matched.

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

SEC's fair-access policy asks requesters to identify themselves. The default names this actor; replace it with your own name and contact if you are running at volume. It cannot be empty — SEC returns 403 for an empty User-Agent.

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

Optional. This is a keyless public government API with no anti-bot layer, so a proxy is not needed.

## Actor input object example

```json
{
  "searchQueries": [
    "\"climate risk\""
  ],
  "maxItemsPerQuery": 300,
  "userAgent": "xtracto-sec-edgar-filings-actor (+https://apify.com/xtracto)"
}
```

# Actor output Schema

## `overview` (type: `string`):

Dataset items shown in the 'Filings' view.

## `items` (type: `string`):

Every record this run produced, with all fields, as JSON.

# 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 = {
    "searchQueries": [
        "\"climate risk\""
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("xtracto/sec-edgar-filings-search").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 = { "searchQueries": ["\"climate risk\""] }

# Run the Actor and wait for it to finish
run = client.actor("xtracto/sec-edgar-filings-search").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 '{
  "searchQueries": [
    "\\"climate risk\\""
  ]
}' |
apify call xtracto/sec-edgar-filings-search --silent --output-dataset

```

## MCP server setup

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

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/xhaRF15FD8aJL1Qah/builds/ZZlUNdocR5PS9dNL7/openapi.json
