# SEC Comment Letter Scraper (`goldenrod_serrano/sec-comment-letters`) Actor

SEC comment letters from EDGAR: staff letters and company responses by ticker, CIK or keyword. Topics, comment count, linked filings. No API key.

- **URL**: https://apify.com/goldenrod_serrano/sec-comment-letters.md
- **Developed by:** [Paopao Studio](https://apify.com/goldenrod_serrano) (community)
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.00 / 1,000 comment letters

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 Comment Letter Scraper — EDGAR UPLOAD & CORRESP Tracker

**See what the SEC asked a company to fix in its 10-K, S-1 or proxy, and how the company answered, straight from EDGAR.** When the SEC's Division of Corporation Finance reviews a filing, it sends a **comment letter** (filed on EDGAR as `UPLOAD`) and the company replies with a **response letter** (`CORRESP`). EDGAR makes the whole exchange public once the review is closed. This Actor finds those letters by date, company or keyword and returns one clean row per letter: company, ticker, CIK, letter type, the filing under review (with a link), number of comments, rule-based topic tags (non-GAAP, revenue recognition, segments, China/VIE, crypto, AI…), a one-line summary, the first comment excerpt, and links to the original documents.

No login. No API key. No proxy. No AI or LLM: topics and summaries come from transparent keyword rules, so the same letter always gives the same output.

> Real examples from our test runs (letters released by EDGAR in Oct–Nov 2026): **NVIDIA** — 4 comments on its FY2025 10-K and a May 2025 8-K, starting with its non-GAAP margin excluding the $4.5B inventory charge · **Avantor** — 3 comments, adjusted operating income shown without the GAAP measure · **Madison Air Solutions** — 19 comments on its draft S-1 · **Enviri** — 12 comments on a Form 10-12B spin-off · **Quanta Services** — revenue recognition on $23.76B of remaining performance obligations · **Bilibili** — 4-comment response on its 20-F.

### Who uses SEC comment letters

| You are | What you do with it |
|---|---|
| **Compliance, SEC reporting, audit** | Benchmark your filings. See which issues the staff raises right now (non-GAAP, segment reporting after ASU 2023-07, KPIs, China/VIE, crypto) and how peers in your industry answered, before your own 10-K goes out. |
| **Investment research / short sellers / credit** | A comment letter on revenue recognition, going concern or internal controls is a quiet red flag. Track your watch list by ticker and get every new letter, with the filing it refers to and the SEC's deadline. |
| **Law firms and accounting firms (business development)** | Companies in an active SEC review (IPO drafts, spin-offs, SPAC deals, going-private proxies, 20-F filers) need securities counsel and technical accounting help. Filter by topic, form and comment count to find them. |
| **Journalists and academics** | Build a dataset of letters by topic and year without parsing EDGAR yourself. |

### Quick start

**Free preview:** switch on **Free sample mode** → 5 letters released in the last 7 days, not charged.

**Latest SEC staff comment letters (last 14 days)** — the default form:

```json
{ "daysBack": 14, "forms": ["UPLOAD"], "letterTypes": ["sec_staff_comment"], "maxResults": 20 }
```

**Full comment history for a watch list (tickers or CIKs):**

```json
{ "companies": ["AAPL", "NVDA", "TSLA"], "startDate": "2023-01-01", "maxResults": 50 }
```

**Full-text search: every staff letter that mentions "non-GAAP" this year:**

```json
{ "keywords": ["non-GAAP"], "forms": ["UPLOAD"], "letterTypes": ["sec_staff_comment"], "startDate": "2026-01-01", "maxResults": 100 }
```

**Company responses about hot topics in the last 30 days:**

```json
{ "daysBack": 30, "forms": ["CORRESP"], "letterTypes": ["company_response"],
  "topics": ["non_gaap_measures", "revenue_recognition", "segment_reporting", "crypto_digital_assets", "china_hk_vie"], "maxResults": 30 }
```

**Weekly monitor (schedule it):** add `"changeTracking": true` and a `stateKey`. Later runs only push letters you have not received, so you are **never charged twice for the same letter**.

#### How the Actor finds letters (three modes, picked automatically)

| Your input | Source used | Date filter |
|---|---|---|
| nothing special (default) | EDGAR daily form index (`/Archives/edgar/daily-index/`) | **release date** on EDGAR, up to 120 days per run |
| `companies` (ticker or CIK) | SEC submissions API (`data.sec.gov/submissions/`) | filing date, default last 365 days, up to 10 years |
| `keywords` | EDGAR full-text search (`efts.sec.gov/LATEST/search-index`) | filing date, default last 365 days, up to 10 years |

**Important timing note:** EDGAR releases comment letters **no earlier than 20 business days after the review is closed**, so a letter released today is often dated months earlier (NVIDIA's July 2025 letter was released on 2026-01-13). `released_date` is when it became public; `letter_date` is when it was written.

### Filters

- `forms` — `UPLOAD` (SEC → company), `CORRESP` (company → SEC), or both.
- `letterTypes` — rule-based class of each letter: `sec_staff_comment`, `sec_review_complete` ("we have completed our review"), `sec_letter_other`, `company_response`, `acceleration_request` (requests to declare a registration effective; off by default, they are short and repetitive), `company_letter_other`.
- `topics` — keep letters tagged with any of these topics (see list below).
- `minComments` — at least N numbered comments (e.g. 5 = a heavy review).
- `skipFundFilers` — on by default; most `CORRESP` volume comes from mutual funds and ETFs. Only applies when you do not list companies.
- `maxResults`, `maxLettersToScan`, `requestsPerSecond` (default 5, max 9).

**Topics (31, keyword rules, counted only in the letter body):** non_gaap_measures, revenue_recognition, segment_reporting, mdna_results_trends, liquidity_capital_resources, going_concern, goodwill_impairment, critical_accounting_estimates, income_taxes, business_combination_ma, spac, china_hk_vie, crypto_digital_assets, cybersecurity, climate_esg, risk_factors, executive_compensation, related_party, internal_controls, legal_contingencies, fair_value_derivatives_warrants, leases, stock_compensation, kpis_operating_metrics, oil_gas_mining_reserves, auditor_pcaob, offering_terms_dilution, going_private_deregistration, artificial_intelligence, tariffs_trade, fund_prospectus.

### Output fields

One row per letter. Full real record: [`docs/example_output.json`](docs/example_output.json).

| Field | Meaning | Real example (NVIDIA, 2025-07-22) |
|---|---|---|
| `company_name`, `ticker`, `cik` | Company and its SEC id | NVIDIA CORP, NVDA, 1045810 |
| `form_type`, `letter_type`, `letter_direction` | Which letter it is | UPLOAD, sec_staff_comment, sec_to_company |
| `letter_date`, `filed_date`, `released_date` | Written / filed / made public | 2025-07-22, 2025-07-22, 2026-01-13 |
| `subject` | The "Re:" line | Form 10-K for the Fiscal Year Ended January 26, 2025 · Form 8-K furnished May 28, 2025 |
| `referenced_filings` | Filings named in the subject | 10-K period 2025-01-26; 8-K filed 2025-05-28 |
| `related_filings` | Those filings matched on EDGAR, with links | 10-K 0001045810-25-000023, 8-K 0001045810-25-000115 |
| `comment_count` | Numbered comments (or responses) | 4 |
| `response_deadline_business_days` | Reply deadline the staff asked for | 10 |
| `responds_to_letter_dated` | For responses: which SEC letter it answers | (on NVIDIA's 2025-07-31 response: 2025-07-22) |
| `topics`, `topic_hits` | Rule-based topic tags with hit counts | non_gaap_measures 3, segment_reporting 3, revenue_recognition 2, income_taxes 1 |
| `first_comment_excerpt` | First ~320 characters of comment 1 | "We note that you disclose non-GAAP margin and Non-GAAP diluted earnings per share excluding the $4.5 billion inventory charge…" |
| `summary` | One-line rule-based summary | SEC staff comment letter on 10-K for the period ended 2025-01-26 and 1 more filing(s)… |
| `sic_code`, `sic_description`, `exchanges`, `state_of_incorporation`, `business_city`, `business_state` | Company profile | 3674 Semiconductors & Related Devices, Nasdaq, DE, SANTA CLARA, CA |
| `document_url`, `text_url`, `filing_index_url`, `edgar_company_url` | Links to the original SEC documents | sec.gov links |
| `text_available`, `text_source`, `text_chars`, `document_truncated` | How the text was read | true, text_extract, 3865, false |

With change tracking on, rows also get `change_type` ("new"), `is_new_company`, `company_first_seen_at` and `previous_letter_date`.

Exports to JSON, CSV, Excel, or via API / webhooks / Zapier / Make like any Apify dataset. The **Referenced filings & tracking** view shows the filing each letter is about and which SEC letter each response answers.

### Change tracking (optional)

Turn on **Change tracking** (`changeTracking: true`) with a `stateKey` and schedule the Actor. It remembers every letter (accession number) and company it has seen under that key. Letters never change after release, so every delivered row is `change_type: "new"`; `is_new_company` tells you whether the company is new to your list, and `previous_letter_date` shows the last letter you already had from it.

**Caps only limit output.** Every candidate letter in the window is saved as seen, including letters cut by *Max results* or *Max letters to scan*, so a rerun with the same input outputs and charges nothing. `RUN_SUMMARY` reports `skipped_by_max_results` and `skipped_by_max_scan`; raise the caps on the first (baseline) run if those are not 0. Only letters that failed to download (retried next run) or were stopped by your *max charge per run* stay unseen.

Real test (2026-11-05): 14-day UPLOAD staff comments, run 1 → 20 letters; same input again → 0 letters, `skipped_seen: 75`, 0 charges. Keyword "non-GAAP" since 2026-01-01: run 1 → 25 letters (63 full-text hits), run 2 → 0.

### Pricing (pay per event)

| Event | When it is charged | Price |
|---|---|---|
| `letter` | One matched comment letter pushed to your dataset | **$0.01** (= $10 per 1,000 letters) |

That is the only charge. No start fee. Index downloads, company lookups, letters removed by your filters, download errors and **Free sample mode** runs are not charged. Change tracking never re-charges a letter you already got. Set *Maximum cost per run* and the Actor stops cleanly at your limit.

Illustration (not a measured average): a weekly monitor of new SEC staff comment letters at ~40 a week ≈ 170 letters a month ≈ **$1.70/month**.

### Data source, legality and privacy

- Source: SEC EDGAR public records only — `www.sec.gov/Archives/` (daily form index and the letters themselves), `data.sec.gov/submissions/` and EDGAR full-text search (`efts.sec.gov`). U.S. government public records.
- Follows the SEC **fair-access policy**: declared User-Agent with a contact email, default 5 requests/second (hard cap 9; SEC's limit is 10). Only paths that `robots.txt` allows (`/Archives/`); never `/cgi-bin/`. Each letter is one request (download capped at 4 MB).
- **No personal data in the output.** Letters are signed by SEC staff and company officers and list phone numbers; this Actor does not output names, signatures, phone numbers or email addresses (they are scrubbed from excerpts). Company business city/state comes from the public EDGAR company record.

### Limits

- Topics and letter types are **keyword rules**, not legal analysis. Read the letter (link in every row) before relying on it.
- Some older letters are scanned PDFs without a text layer; they still appear with `text_available: false` and no topics.
- `comment_count` counts numbered paragraphs; a few letters use unusual numbering.
- `related_filings` is matched by form type and date (±3 days) or report period; very old or unusual filings may not match.
- Full-text search covers 2001 onwards; daily-index mode is limited to 120 days per run.

### FAQ

**Why is a letter from April released in October?** The SEC publishes comment letters at least 20 business days after it completes a review. Use `released_date` for "what's new", `letter_date` for "when it happened".

**How do I see the whole conversation for one filing?** Use `companies` with a ticker and sort by `letter_date`: SEC letters and company responses alternate, and each response has `responds_to_letter_dated`.

**Why did a company I listed not resolve?** Use the 10-digit CIK. Tickers are looked up in SEC's `company_tickers.json`; delisted companies may not be there. Unresolved inputs are listed in `RUN_SUMMARY.unresolved_companies`.

**Why is there a "Free sample mode" switch instead of "run with empty input"?** Apify fills the form defaults into the input, so an empty input never reaches the Actor. The switch makes the free preview explicit.

### Related Actors by PaoPao Studio

- [SEC Form D Scraper — Startup Funding Data](https://apify.com/goldenrod_serrano/sec-form-d-funding-signals) — every new Reg D private round from EDGAR, with amount, industry and state.
- [ATS Jobs Monitor for Recruiter BD](https://apify.com/goldenrod_serrano/ats-hiring-signals) — new and closed jobs from Greenhouse, Lever, Ashby, Workable, SmartRecruiters and Recruitee.
- [Workday Jobs Monitor for Recruiter BD](https://apify.com/goldenrod_serrano/workday-hiring-signals) — the same for companies hiring on Workday.

SEC comment letters (this Actor) + Form D filings = two official EDGAR signals for compliance, research and BD teams.

### Changelog

- 1.0 — first release: daily-index, company and full-text search modes; rule-based letter types, topics and summaries; related-filing links; change tracking; PPE `letter` event.

***

Made by PaoPao Studio. Questions or feature requests: use the Issues tab. Not affiliated with the U.S. SEC.

# Actor input Schema

## `sampleMode` (type: `boolean`):

Turn on for a free preview: 5 letters released by the SEC in the last 7 days (operating companies). All other settings are ignored and nothing is charged. Leave off for a normal run (each pushed letter = one 'letter' event).

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

Only letters for these companies, e.g. AAPL, TSLA, 320193. Uses the SEC submissions API. With Companies set, the date range is the letter's EDGAR filing date (default: last 365 days). Leave empty to get every company.

## `keywords` (type: `array`):

Search the text of UPLOAD/CORRESP letters with SEC EDGAR full-text search, e.g. non-GAAP, "key performance indicators", crypto, "variable interest entity". Phrases with spaces are searched as exact phrases. Date range = filing date (default last 365 days). Combine with Companies to search one company's letters.

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

UPLOAD = letters from SEC staff to the company (comments, 'review complete'). CORRESP = letters from the company to the SEC (responses, acceleration requests).

## `letterTypes` (type: `array`):

Rule-based type from the letter text. Acceleration requests (short 'please declare our S-1 effective' letters) are excluded by default.

## `topics` (type: `array`):

Keep only letters that mention at least one of these topics (rule-based keyword dictionary, no AI). Empty = all.

## `minComments` (type: `integer`):

Keep only letters with at least this many numbered comments (0 = no filter).

## `daysBack` (type: `integer`):

Window size in calendar days, ending today. Default mode (no companies/keywords): days the SEC *released* letters on EDGAR (max 120). Company or keyword mode: letter filing date (default 365, max 3660). Ignored if Start date is set.

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

YYYY-MM-DD. Leave empty to use Days back.

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

YYYY-MM-DD. Defaults to today.

## `skipFundFilers` (type: `boolean`):

Most CORRESP volume is mutual-fund / ETF / annuity prospectus correspondence. On by default (ignored when you list Companies).

## `maxResults` (type: `integer`):

Stop after this many matching letters (each one is one charged 'letter' event).

## `maxLettersToScan` (type: `integer`):

Safety cap on how many candidate letters are downloaded and read in one run (never charged).

## `changeTracking` (type: `boolean`):

Remember every letter this task has already seen (named key-value store 'sec-comment-letters-state'). Next runs output only letters not seen before, so schedules never pay twice. Rows get is_new_company / previous_letter_date.

## `stateKey` (type: `string`):

Separate change-tracking memory per watchlist (e.g. 'law-firm-bd', 'my-portfolio').

## `linkReferencedFilings` (type: `boolean`):

Look up the company on data.sec.gov (one cached request per company) to add ticker, SIC, exchanges and the accession/URL of the 10-K / S-1 / proxy the letter is about.

## `requestsPerSecond` (type: `integer`):

SEC fair-access limit is 10/s; capped at 9. Default 5.

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

SEC asks automated tools to declare who they are, e.g. 'Your Company your@email.com'. Leave empty to use the Actor's default declared agent.

## Actor input object example

```json
{
  "sampleMode": false,
  "companies": [
    "AAPL",
    "NVDA"
  ],
  "keywords": [
    "non-GAAP"
  ],
  "forms": [
    "UPLOAD",
    "CORRESP"
  ],
  "letterTypes": [
    "sec_staff_comment",
    "sec_review_complete",
    "sec_letter_other",
    "company_response",
    "company_letter_other"
  ],
  "minComments": 0,
  "daysBack": 14,
  "skipFundFilers": true,
  "maxResults": 20,
  "maxLettersToScan": 500,
  "changeTracking": false,
  "stateKey": "default",
  "linkReferencedFilings": true,
  "requestsPerSecond": 5
}
```

# Actor output Schema

## `letters` (type: `string`):

Letters with company, form, dates, referenced filing, topics and summary (dataset view 'letters').

## `runSummary` (type: `string`):

Mode, window, candidates, fetched, matched and pushed counts.

# 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 = {
    "forms": [
        "UPLOAD",
        "CORRESP"
    ],
    "daysBack": 14,
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("goldenrod_serrano/sec-comment-letters").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 = {
    "forms": [
        "UPLOAD",
        "CORRESP",
    ],
    "daysBack": 14,
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("goldenrod_serrano/sec-comment-letters").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 '{
  "forms": [
    "UPLOAD",
    "CORRESP"
  ],
  "daysBack": 14,
  "maxResults": 20
}' |
apify call goldenrod_serrano/sec-comment-letters --silent --output-dataset

```

## MCP server setup

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

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/nMJnzu3S9LT0xI9DB/builds/jBMb841x9JtyR124L/openapi.json
