# SEC Earnings Release Scraper — Text & Metrics (`sourcesauce/sec-earnings-release`) Actor

Parsed earnings-release text and headline metrics from SEC 8-K filings — not just a link to the filing. Get the full quarterly press release body plus revenue, EPS, margin and net income figures, each with its SEC source URL. Financial data for analysts, investor relations and AI agents.

- **URL**: https://apify.com/sourcesauce/sec-earnings-release.md
- **Developed by:** [Source Sauce](https://apify.com/sourcesauce) (community)
- **Categories:** News, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 records

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/platform/actors/running/actors-in-store#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 Earnings Release Scraper — Text & Metrics

**Get the actual earnings release text from SEC 8-K filings — not just a link to the filing.**

Most SEC tools hand you filing metadata and a URL. The numbers you actually want live inside an
exhibit attached to the filing, and the 8-K's own primary document is a cover page that contains no
financials at all. This actor resolves the right exhibit, strips it to clean text, and returns it
alongside the headline figures.

*Unofficial. Not affiliated with or endorsed by the U.S. Securities and Exchange Commission.*

### What you get per filing

```json
{
  "company": "Apple Inc.",
  "tickers": ["AAPL"],
  "cik": "0000320193",
  "accession": "0000320193-26-000018",
  "form": "8-K",
  "items": ["2.02", "9.01"],
  "filing_date": "2026-07-30",
  "report_date": "2026-07-30",
  "release_document": "a8-kex991q3202606272026.htm",
  "release_chars": 10468,
  "release_text": "Apple reports third quarter results ... quarterly revenue of $109.4 billion, up 16 percent year over year ...",
  "metrics": {
    "revenue": "$109.4 billion",
    "eps_diluted": "$2.02",
    "gross_margin_pct": "50.1",
    "net_income": "$27.5 billion"
  },
  "source_url": "https://www.sec.gov/Archives/edgar/data/320193/000032019326000018/a8-kex991q3202606272026.htm",
  "co_registrants": []
}
```

Every record carries `source_url` — the exact SEC document the text came from, so any figure can be
checked at the primary source.

**One filing is one record, even when several companies file it together.** Utility holding companies
and REITs routinely file a single 8-K under a parent plus its subsidiaries or operating partnership.
SEC's index lists each registrant separately; we return one record and name the others in
`co_registrants`, so you are billed once for one document:

```json
"company": "ALLIANT ENERGY CORP",
"cik": "0000352541",
"co_registrants": [
  {"cik": "0000052485", "company": "INTERSTATE POWER & LIGHT CO"},
  {"cik": "0000107832", "company": "WISCONSIN POWER & LIGHT CO"}
]
```

### Who uses this

- **Equity analysts and quant funds** — quarterly results in structured form the moment they are
  filed, rather than waiting for an aggregator to pick them up.
- **Investor relations and comms teams** — pull competitors' earnings press releases into one place
  on results day.
- **AI agents and retrieval pipelines** — `release_text` is clean prose paired with a `source_url`,
  which is what a RAG pipeline needs and what a filing-metadata API does not give you.
- **Financial data products** — revenue, EPS, gross margin and net income as parsed fields, with the
  release body kept alongside so any number can be audited back to the source.

### Common questions

- **Is this 10-Q or 10-K data?** No — 8-K earnings releases only, items 2.02 and 7.01. That is where
  US issuers publish quarterly results first; the 10-Q follows weeks later.
- **Do I get full financial statements?** No. You get the press release body plus the four headline
  metrics above. Statement tables are not parsed into fields — see Honest limitations.
- **How current is it?** As current as EDGAR itself; filings are retrievable within minutes of
  acceptance.
- **Can I run it for a whole watchlist?** Yes — `tickers` takes an array, and `limit` controls how
  many filings come back per issuer.
- **Can I get every issuer reporting on a given day, without a ticker list?** Yes — set
  `mode` to `fullMarket` and optionally `date`. That returns every 8-K item-2.02 filing on the most
  recent published EDGAR index day. For scale: **57 issuers on 2026-07-31**, against a market-wide
  average of **about 90 item-2.02 filings per business day** measured across 2026-07-20..31.
- **Am I charged twice when a parent and its subsidiary file the same 8-K?** No. One filing is one
  charge; the other registrants are listed in `co_registrants` on the same record.

### Input

| Field | Type | Notes |
|---|---|---|
| `mode` | string | `watchlist` (default) or `fullMarket`. Full-market ignores `tickers`/`ciks` and returns every issuer reporting results on one EDGAR index day. |
| `date` | string | `fullMarket` only. `YYYY-MM-DD`; defaults to today. Walks back to the most recent published index, so weekends and holidays return the last trading day rather than nothing. |
| `maxFilings` | int | `fullMarket` only. Caps how many filings are examined in one run. Default 400. |
| `tickers` | string\[] | e.g. `["AAPL","MSFT"]`. Resolved via SEC's own ticker→CIK map. |
| `ciks` | string\[] | Use when a ticker isn't in SEC's map (ETFs and some issuers are missing). |
| `limit` | int | Filings per issuer, newest first. Default 2. |
| `includeText` | bool | Set false for metadata + metrics only (smaller payloads). |
| `contactEmail` | string | **Required.** The SEC requires EDGAR requests to identify the requester with a contact email. Sent only to the SEC in the User-Agent header — never stored or shared otherwise. |

Unresolved tickers are **reported, never silently dropped** — a lookup miss means "not in SEC's map",
not "company doesn't exist".

### Which filings it covers

8-K filings carrying **item 2.02** (Results of Operations) or **item 7.01** (Regulation FD) — the two
item codes under which US issuers publish quarterly results. Item 7.01 also captures the monthly
credit-statistics releases that card issuers file.

### Honest limitations

- **`release_text` is the authoritative output; `metrics` is a convenience layer.** The parser is
  deliberately conservative and returns `null` rather than a number it can't stand behind.
- **Some issuers publish figures only in tables** (ExxonMobil reports `114,529` with units declared
  in a column header). Rather than guess a magnitude, those fields come back `null` — the full text
  is still there.
- **Non-GAAP labels are not silently mapped.** A company reporting only "core EPS" returns `null` for
  `eps_diluted`, because those are different measures.
- Verified across a live sample of 10 large-cap issuers (Apple, Microsoft, NVIDIA, JPMorgan,
  Coca-Cola, Delta, Goldman Sachs, P\&G, ExxonMobil, Tesla): release text resolved for **10/10**,
  headline revenue for 7/10, with the 3 abstentions correct per the rules above.

### Notes on sourcing

Data comes from the SEC's public EDGAR system, accessed with a declared User-Agent and self-throttled
well inside SEC's published request guidance. No login, paywall, or access control is bypassed.

### Development

```bash
uv run --with pytest pytest -q                    # 21 unit tests, no network
uv run python -m src.run --tickers AAPL --limit 1 --user-agent "you you@example.com"
```

# Actor input Schema

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

Watchlist returns earnings releases for the issuers you list. Full market returns every issuer that reported results on a given date — no ticker list needed. Full market reads roughly 300 filings per day and takes a few minutes.

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

Stock tickers to fetch, e.g. AAPL. Resolved via SEC's own ticker-to-CIK map; a ticker missing from that map is reported, never silently dropped. Ignored in full-market mode.

## `date` (type: `string`):

Which day's filings to read, as YYYY-MM-DD. Leave empty for the most recent published day. Weekends and holidays have no filings, so the actor walks back to the last trading day that does.

## `maxFilings` (type: `integer`):

Upper bound on how many of the day's 8-K filings are examined. Roughly 300 are filed on a typical business day and about a third report results. Lower this to shorten a run.

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

SEC CIK numbers, for issuers whose ticker is not in SEC's map. Used in addition to tickers.

## `limit` (type: `integer`):

How many matching 8-K filings to return per issuer, newest first.

## `includeText` (type: `boolean`):

If false, returns metadata and metrics only (smaller payloads).

## `contactEmail` (type: `string`):

Required by the SEC: EDGAR requests must carry a User-Agent identifying the requester with a contact email. Your email is sent only to the SEC, never stored or shared otherwise. Replace the prefilled address with your own for production use.

## Actor input object example

```json
{
  "mode": "watchlist",
  "tickers": [
    "AAPL",
    "MSFT"
  ],
  "maxFilings": 400,
  "limit": 2,
  "includeText": true,
  "contactEmail": "smazing.actors@gmail.com"
}
```

# 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",
        "MSFT"
    ],
    "contactEmail": "smazing.actors@gmail.com"
};

// Run the Actor and wait for it to finish
const run = await client.actor("sourcesauce/sec-earnings-release").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",
        "MSFT",
    ],
    "contactEmail": "smazing.actors@gmail.com",
}

# Run the Actor and wait for it to finish
run = client.actor("sourcesauce/sec-earnings-release").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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",
    "MSFT"
  ],
  "contactEmail": "smazing.actors@gmail.com"
}' |
apify call sourcesauce/sec-earnings-release --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=sourcesauce/sec-earnings-release",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/NpXJofXbjKLkcfPo7/builds/o0x6UnSeU3csXNdXK/openapi.json
