# SEC Fundamentals: Revenue, EPS and Cash Flow (`lone_rachis/sec-xbrl-fundamentals`) Actor

Annual and quarterly financials from the XBRL data companies file with SEC: revenue, profit, EPS, balance sheet and cash flow by ticker or CIK, with the source tag next to each value. Screen mode lists every company that reported a metric for a calendar period.

- **URL**: https://apify.com/lone_rachis/sec-xbrl-fundamentals.md
- **Developed by:** [Kesav Kumar Jayakumar](https://apify.com/lone_rachis) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.20 / 1,000 company periods

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

### What does SEC Fundamentals do?

**SEC Fundamentals** returns the financial statement figures that US public companies file with SEC in XBRL, as flat rows you can sort and export. It has two modes.

In **companies** mode you give tickers or CIKs, up to 500 per run, and choose annual figures, quarterly figures or both for the last 1 to 20 years. Each company and fiscal period becomes one row with revenue, gross profit, operating income, net income, diluted EPS, total assets, total liabilities, stockholders' equity, cash, operating cash flow, capital expenditure, free cash flow and shares outstanding. The row also holds the period's start and end dates, the fiscal year and quarter, the form (10-K or 10-Q), its filing date and its accession number.

In **screen** mode you pick one or more metrics and a calendar period, such as CY2024 or CY2025Q2. You get every company that reported the first metric for that period, highest first, with an optional minimum and maximum.

Every value sits next to the XBRL tag it came from, such as `us-gaap:Revenues`, and a flag that says whether the Actor derived it. A metric the company did not report stays empty. Nothing is estimated.

The Actor reads three JSON sources SEC publishes for automated use: the ticker list, each company's XBRL facts and SEC's frames for one calendar period. It names itself and a contact address in every request, as SEC asks, and sends at most 5 requests a second. You pay per delivered row. A ticker SEC does not list, a company without US GAAP figures and work the run did not reach cost nothing.

### Why use SEC Fundamentals?

SEC publishes every figure a company tags in its 10-K and 10-Q filings, but the file for one large company holds 3 to 8 MB of facts. Each figure is repeated in every later filing that shows it again as a comparative, and the same line can move between tags from one year to the next. Apple's revenue sits under three different tags between fiscal 2009 and 2025. Banks report net revenue under names an industrial company never uses. This Actor picks one value per metric and period by a fixed rule, places it in the company's own fiscal year or quarter, and says which tag it used.

What you get:

- **Figures as filed, with their source.** Each value comes with its tag and a derived flag, and each row with the filing it came from and a link to that filing on sec.gov.
- **Fiscal periods in the company's own calendar.** Years that end in September (Apple), June (Microsoft) or January (Walmart) stay the company's fiscal years. Quarters follow each other with no gap, and Q4, which has no 10-Q of its own, is built from the 10-K.
- **Restated or as first reported.** `latest-filed` (the default) takes the figure from the newest filing that reports the period, so restatements and stock splits are in it. `first-filed` takes the figure as it was first reported.
- **A screen across the market.** Every company that reported a metric for a calendar period, in one run. A screen of 5,109 companies took 15 seconds.
- **Clear statuses.** `ok`, `not-found`, `no-data`, `failed` or `skipped`, each with a reason in a sentence. Only `ok` rows are charged.
- **Fair use of SEC.** A declared User-Agent, at most 5 requests a second, a wait on HTTP 429 and a full stop after two HTTP 403 answers in a row.

Each claim above has a test behind it:

| What you get | How it works | The test that backs it |
| --- | --- | --- |
| **One row per company and fiscal year, matching the 10-K** | Periods come from each fact's start and end dates, since the fiscal year SEC stamps on a fact belongs to the filing that carried it. The reference filing of a period is the first one that reported it as its own period. | "the prefill: three companies, three fiscal years each, nine charged rows with the 10-K figures", "Apple: the fiscal year ends in late September, and FY2025 matches its 10-K", "Microsoft: the fiscal year ends on 30 June", and the live test "live: the latest fiscal year of each prefill company matches the 10-K facts in SEC companyconcept" (13 Oct 2026), which compares each row with a second SEC endpoint. |
| **One value per metric, with its tag** | Each metric has a fixed list of tags, tried in order inside the chosen filing. The tag that won is written next to the value. | "Apple reported revenue under three tags over the years, and each year gets one value", "Goldman Sachs reports revenue only as RevenuesNetOfInterestExpense", "Chevron: Revenues wins over the smaller contract revenue; capex comes from PaymentsToAcquireProductiveAssets", "JPMorgan, a bank: net revenue under Revenues; no operating income, no capex, so no free cash flow". |
| **No invented numbers** | A value is a fact from the file with that tag and those dates. Derived values use only reported figures and are flagged. A metric with no fact stays empty. | "no invented numbers: every reported value is a fact in the file with that tag and those dates", "Berkshire Hathaway tags EPS and shares only per share class, so both stay empty", "Walmart: the fiscal year ends in January; gross profit is derived; liabilities stay empty because of redeemable minority interest". |
| **Quarters, Q4 included** | A quarter takes the 3-month figure when the filing reports one, and the difference of two year-to-date figures when it does not. Q4 is the fiscal year minus nine months. EPS is never subtracted. | "Apple Q4 FY2025 runs from the day after Q3 to the year end; its flows are the year minus nine months; EPS stays empty", "Apple Q2 FY2026: income is reported for the quarter; cash flow is six months minus three", "quarters follow each other without gaps or repeats, for a September, a June and a January year", "quarterly and annual together for Walmart: Q4 comes from the 10-K, and derived fields are listed". |
| **As first reported, or restated** | The filing decides first and the tag second, so `first-filed` returns the oldest filing's own figure. | "first-filed returns figures as first reported: Apple FY2018 EPS before the 2020 split", "first-filed gives a figure as first reported; latest-filed gives the restated one (Apple EPS before and after the 2020 split)". |
| **A screen of every company for a calendar period** | Screen mode reads one SEC frame per tag a metric can come from and keeps one row per company, sorted high to low. A frame SEC does not have counts as empty. | "screen: every company that reported revenue for CY2024, high to low, the frames that do not exist skipped", "screen on diluted EPS for a calendar quarter", "screen with no company inside the filters writes one free row and succeeds", and the live test "live: a revenue screen for CY2024, twenty companies, highest first". |
| **No charge for what it could not read** | A ticker SEC does not list, an IFRS filer and a CIK without XBRL data get a free row each. A file that is not JSON gets a free `failed` row, and the next company is still read. Five failures in a row stop the run. | "a ticker SEC does not list, an IFRS filer, a CIK without data and a repeat are free rows; the rest is charged", "a company file that is not JSON is a free failed row; the next company is still read", "N6 five company files in a row failing with server errors stop the run, free; a run with no row is marked failed". |
| **A spending cap that stops the run** | Set a maximum cost per run, or a maximum number of rows. The run stops before it charges past it and lists what it did not deliver. | "P6 the maximum cost per run stops delivery cleanly; what was not delivered is listed, free", "maxResults stops delivery; what was not delivered is listed, free". |
| **A restart repeats nothing** | A run that restarts reads its own rows first and skips every company and period already written. | "B2 a crash right after a row is written delivers and charges nothing twice when the run resumes", "P1 on migrating the run saves its summary, and the restarted run repeats nothing". |
| **Fair use of SEC** | Requests start at least 210 ms apart, at most 3 at a time. A 429 is waited out. A 403 gets one retry after 10 seconds, then the run sends nothing more. SEC's answer for a file it does not have (404) is told apart from a refusal. | "N3 a refusal on one file and again on its retry stops every request to SEC; what was not reached is skipped, free", "N4 a 429 is waited out and the company is still read", "a company or frame SEC does not have (404 with a NoSuchKey XML body) is a free row, never a refusal", "live: the whole live suite sent at most 60 requests to SEC". |

Plus what the Apify platform adds around it:

- **API access.** Start runs and read results with the Apify API or the JavaScript and Python clients.
- **Scheduling.** Refresh a watch list every week, or after each earnings season.
- **Integrations.** Send rows to Make, Zapier, Google Sheets or any webhook.
- **Monitoring.** Run history, logs and alerts for failed runs.

Typical uses are a spreadsheet of five years of figures for a watch list, the inputs of a valuation model, a quarterly check of margins across a sector, a list of every company above a revenue size for a sales team, and a research dataset that needs to show where each number came from.

### What data can SEC Fundamentals extract?

Each company and period becomes one row in the dataset. The most useful fields:

| Field | Type | What it holds |
| --- | --- | --- |
| `status` | string | `ok`, `not-found`, `no-data`, `failed` or `skipped`. |
| `mode`, `input` | string | The mode, and the entry from your list this row answers (or the calendar period in a screen). |
| `cik`, `ticker`, `companyName` | string | SEC's 10-digit number for the company, its ticker from SEC's list and its name. |
| `periodType`, `fiscalYear`, `fiscalPeriod` | string, number, string | `annual` or `quarterly`; the fiscal year; `FY` or `Q1` to `Q4`. |
| `periodStart`, `periodEnd` | string | The first and last day of the period, YYYY-MM-DD. |
| `form`, `filingDate`, `accessionNumber` | string | The filing the period comes from: 10-K or 10-Q, its date and EDGAR's number for it. |
| `calendarPeriod`, `location` | string | Screen mode only: the calendar period, and the location SEC's frames give for the business address, such as US-CA. |
| `currency` | string | The currency of the money figures, nearly always USD. |
| `revenue`, `grossProfit`, `operatingIncome`, `netIncome` | number | Income statement figures for the period. |
| `dilutedEps` | number | Diluted earnings per share, in the currency per share. |
| `totalAssets`, `totalLiabilities`, `stockholdersEquity`, `cash` | number | Balance sheet figures on the last day of the period. |
| `operatingCashFlow`, `capitalExpenditure`, `freeCashFlow` | number | Cash flow figures for the period. Capital expenditure is a positive number. |
| `sharesOutstanding`, `sharesOutstandingDate` | number, string | Common shares outstanding and the date of that count. |
| `<metric>Tag`, `<metric>Derived` | string, boolean | Next to every metric: the XBRL tag it came from, or the formula for a derived value, and whether it was derived. |
| `derivedFields` | array | The metrics of the row that were derived. |
| `valueRule` | string | `latest-filed` or `first-filed`. |
| `filingIndexUrl`, `factsUrl` | string | The filing's folder on sec.gov, and the company's XBRL facts file on data.sec.gov. |
| `error`, `errorCode` | string | Why a row is not `ok`, as a sentence and as a short code. |

The **Overview** view shows the company, the period and the headline figures. The **Income statement**, **Balance sheet** and **Cash flow** views show one statement each, and the **Sources** view shows the tag and derived flag of every metric.

Each metric is read from these tags, in this order. The first tag that the chosen filing reports for the period wins.

| Metric | Tags tried, in order (us-gaap unless named) | Derived when |
| --- | --- | --- |
| `revenue` | `Revenues`, `RevenueFromContractWithCustomerExcludingAssessedTax`, `RevenueFromContractWithCustomerIncludingAssessedTax`, `RevenuesNetOfInterestExpense`, `SalesRevenueNet`, `SalesRevenueGoodsNet` | Only in a quarter, by the rule below. |
| `grossProfit` | `GrossProfit` | When GrossProfit is missing: revenue minus cost of revenue (`CostOfRevenue`, `CostOfGoodsAndServicesSold`, `CostOfGoodsSold`). |
| `operatingIncome` | `OperatingIncomeLoss` | Only in a quarter. |
| `netIncome` | `NetIncomeLoss`, `ProfitLoss`, `NetIncomeLossAvailableToCommonStockholdersBasic` | Only in a quarter. |
| `dilutedEps` | `EarningsPerShareDiluted`, `EarningsPerShareBasicAndDiluted` | Never. A quarter without its own EPS figure has none. |
| `totalAssets` | `Assets` | Never. |
| `totalLiabilities` | `Liabilities` | When Liabilities is missing: `LiabilitiesAndStockholdersEquity` minus total equity. Left empty when the company reports temporary equity that day. |
| `stockholdersEquity` | `StockholdersEquity`, `StockholdersEquityIncludingPortionAttributableToNoncontrollingInterest` | Never. |
| `cash` | `CashAndCashEquivalentsAtCarryingValue`, `CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalents`, `CashAndDueFromBanks`, `Cash` | Never. |
| `operatingCashFlow` | `NetCashProvidedByUsedInOperatingActivities`, `NetCashProvidedByUsedInOperatingActivitiesContinuingOperations` | Only in a quarter. |
| `capitalExpenditure` | `PaymentsToAcquirePropertyPlantAndEquipment`, `PaymentsToAcquireProductiveAssets` | Only in a quarter. |
| `freeCashFlow` | none | Always: operating cash flow minus capital expenditure, when both are there. |
| `sharesOutstanding` | `CommonStockSharesOutstanding`, then the cover page count `dei:EntityCommonStockSharesOutstanding` of the period's own filing | Never. The cover page count carries its own date in `sharesOutstandingDate`. |

The quarter rule: a figure over a period of time takes the 3-month value when the filing reports one. When it reports only the year to date, as most companies do for cash flow, the quarter is the year to date minus the previous year to date, with the same tag and the same start. Q4 is the fiscal year minus the nine months to Q3. Such a value is flagged as derived, and its tag says what was subtracted.

Where the tag list can be wrong for you: `Revenues` comes first because it is the total line, so for Chevron it includes other income (189,031M against 184,432M of contract revenue for 2025), and for Walmart it includes membership income, which then goes into the derived gross profit. A company that changes tags mid-history can show a step between years. Check the `revenueTag` column when you compare companies.

Every row that is not `ok` carries one of these codes in `errorCode`, so you can count rows by reason without reading the sentence. The sentence in `error` can be reworded in a later version. The code stays.

| `errorCode` | Meaning |
| --- | --- |
| `ticker-not-found` | SEC's ticker list has no such ticker. Give the CIK for a company that is no longer listed. |
| `no-xbrl-data` | SEC has no XBRL financial data for the CIK. Funds and trusts often have none. |
| `no-us-gaap-data` | The company files XBRL, but not in US GAAP. Companies that report under IFRS are not covered. |
| `no-periods` | The company has US GAAP facts, but no period the Actor can place. A new holding company that took over an older ticker has its history under the older CIK. |
| `no-match` | Screen mode: companies reported the metric, but none inside your minimum and maximum. |
| `no-frame-data` | Screen mode: no company reported the metric for that calendar period. |
| `charge-limit` | The run reached your maximum cost per run. |
| `max-results` | The run reached your maximum number of rows per run. |
| `run-time-limit` | The run reached its time limit. |
| `repeated-failures` | Five company files in a row failed with a server or network error, so the run stopped. |
| `aborted` | The run was stopped. |
| `sec-blocked` | SEC refused two requests in a row (HTTP 403), so the run sent nothing more. |
| `not-found` | SEC does not have the file asked for. |
| `rate-limited` | SEC kept answering "too many requests" (HTTP 429) after three waits. |
| `server-error`, `http-error` | SEC answered with an error status. |
| `network-error`, `timeout` | SEC could not be reached, or did not answer within 60 seconds. |
| `too-large`, `bad-response`, `unexpected-redirect` | SEC sent a file over 60 MB, a file the Actor could not read, or a redirect to another site. |
| `other` | Any other reason. The sentence in `error` says what happened. |

### How to get company fundamentals from SEC filings

1. Open the Actor in Apify Console and select the **Input** tab.
2. The form is prefilled with Apple, Microsoft and JPMorgan Chase, annual periods and 3 years, so you can press **Start** to see a result straight away. On 13 Oct 2026 that run returned 9 rows in about 10 seconds: fiscal 2023 to 2025 for Apple and JPMorgan, and fiscal 2024 to 2026 for Microsoft.
3. Under **Companies mode**, replace the list with your own tickers (AAPL, BRK.B) or CIKs (320193), and choose the periods, the number of years and which filing's value you want.
4. For a screen, set **Mode** to `screen` and, under **Screen mode**, pick the metrics and the calendar period. The first metric decides which companies come back and in what order.
5. Press **Start**. In tests on 13 Oct 2026, ten large companies over five years took 6 to 12 seconds.
6. Open the **Output** tab for the table, or one of the statement views. Export it as JSON, CSV or Excel.

To run it from code, send the same input to the Actor through the API:

```json
{
    "mode": "companies",
    "companies": ["AAPL", "MSFT", "AMZN", "JPM", "WMT"],
    "periods": "both",
    "years": 5
}
```

A screen of every company with at least $10 billion of revenue in calendar 2024:

```json
{
    "mode": "screen",
    "metrics": ["revenue", "netIncome", "operatingCashFlow"],
    "period": "CY2024",
    "minValue": 10000000000
}
```

### How much does it cost to get company fundamentals?

You pay per row delivered, and the Apify platform usage for the run is included. A row costs $0.004 on the Free and Bronze plans, so 1,000 rows cost $4.

| Event | When it is charged | Price |
| --- | --- | --- |
| `company-period` | One company and period delivered with status `ok` | $0.004 (Free, Bronze), $0.0036 (Silver), $0.0032 (Gold) |
| Actor start | Once per run, scaled by memory (Apify standard event) | $0.00005 per GB of memory |

Rows with the status `not-found`, `no-data`, `failed` or `skipped` cost nothing, and a company listed twice is read and charged once. You can cap a run with the **Maximum cost per run** setting or with `maxResults`, and the Actor stops cleanly at that limit.

#### How much does one company cost?

One row is one company and one period. Five years of annual figures for one company is 5 rows, $0.02 on the Free and Bronze plans. With quarters as well it is 25 rows (5 years and 20 quarters), $0.10. Ten companies over five years cost $0.20 for annual figures and $1.00 with quarters. A run adds a start fee of about $0.0000125 at the default memory of 256 MB, and there is no second bill for compute.

#### What does a screen cost?

One row per company that reported the metric. The 100 largest companies by 2024 revenue cost $0.40. A full CY2024 revenue screen returned 5,109 companies on 13 Oct 2026, which is $20.44 with no cap. The **Maximum rows per run** field (`maxResults`) is 1,000 by default, so a screen left at the default costs at most $4.00. Set `minValue` to keep only the companies you want.

#### How do I keep a run within budget?

Set **Maximum cost per run** when you start it or in a schedule, or set **Maximum rows per run** (`maxResults`). The run stops before it would charge past that amount, and what it did not deliver gets a free `skipped` row with the code `charge-limit` or `max-results`.

### Input

Open the **Input** tab to see every setting with a short description. Every field has a default, so an empty input reads Apple, Microsoft and JPMorgan Chase, annual, five years. The form has three groups:

- **Companies mode:** `mode` (`companies` by default, or `screen`), `companies`, `periods` (`annual` by default, `quarterly` or `both`), `years` (5 by default, 1 to 20) and `valueRule` (`latest-filed` by default, or `first-filed`).
- **Screen mode:** `metrics` (`revenue` by default), `period` (`CY2024` by default), `minValue` and `maxValue`.
- **Limits and contact:** `maxResults` and `contactEmail`.

`companies` takes tickers as SEC lists them, in any case, with a dot or a dash for share classes (BRK.B and BRK-B are the same), and CIKs with or without leading zeros or the CIK prefix. A company that is no longer listed keeps its CIK, so give the CIK for it. The list holds up to 500 entries.

`years` counts the latest fiscal years with data. For quarters it gives 4 quarters a year, Q4 included, so 5 years of quarters is 20 rows. With `both` you get the two together, newest first, and the fiscal year row comes before its Q4 row on the same end date.

`valueRule` matters when a company has restated a figure or split its stock. `latest-filed` takes the newest filing that reports the period, which is how the company presents that year today. `first-filed` takes the figure as first reported. For Apple's fiscal 2018 diluted EPS that is 2.98 against 11.91, because of the 4 for 1 split in 2020.

`metrics` takes the metric field names: `revenue`, `grossProfit`, `operatingIncome`, `netIncome`, `dilutedEps`, `totalAssets`, `totalLiabilities`, `stockholdersEquity`, `cash`, `operatingCashFlow`, `capitalExpenditure`, `freeCashFlow` and `sharesOutstanding`. `period` is a calendar year (CY2024) or a calendar quarter (CY2025Q2) that has ended. A balance sheet metric is read on the last day of that period. `minValue` and `maxValue` apply to the first metric, in US dollars, or dollars per share for diluted EPS.

`maxResults` caps the rows delivered in a run, 1,000 by default and up to 100,000. Clear the field for no cap.

`contactEmail` is optional. SEC asks every automated tool to name a contact in its requests. Leave it empty to use the Actor developer's address, or give your own if you want SEC to reach you about your runs. It goes to SEC in a request header only and is not stored in the output.

### Output

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel. A run also writes a `SUMMARY` record to its key-value store with the counts of companies asked for and read, the rows by status, the charged rows, the requests sent to SEC and the reason a run stopped early. A run in which nothing could be delivered because of a failure ends with the status Failed and the reason in its message, and the rows stay in the dataset.

A delivered fiscal year and the row of a ticker SEC does not list look like this:

```json
[
    {
        "status": "ok",
        "errorCode": null,
        "error": null,
        "mode": "companies",
        "input": "AAPL",
        "cik": "0000320193",
        "ticker": "AAPL",
        "companyName": "Apple Inc.",
        "location": null,
        "periodType": "annual",
        "fiscalYear": 2025,
        "fiscalPeriod": "FY",
        "calendarPeriod": null,
        "periodStart": "2024-09-29",
        "periodEnd": "2025-09-27",
        "form": "10-K",
        "filingDate": "2025-10-31",
        "accessionNumber": "0000320193-25-000079",
        "currency": "USD",
        "revenue": 416161000000,
        "revenueTag": "us-gaap:RevenueFromContractWithCustomerExcludingAssessedTax",
        "revenueDerived": false,
        "grossProfit": 195201000000,
        "grossProfitTag": "us-gaap:GrossProfit",
        "grossProfitDerived": false,
        "operatingIncome": 133050000000,
        "operatingIncomeTag": "us-gaap:OperatingIncomeLoss",
        "operatingIncomeDerived": false,
        "netIncome": 112010000000,
        "netIncomeTag": "us-gaap:NetIncomeLoss",
        "netIncomeDerived": false,
        "dilutedEps": 7.46,
        "dilutedEpsTag": "us-gaap:EarningsPerShareDiluted",
        "dilutedEpsDerived": false,
        "totalAssets": 359241000000,
        "totalAssetsTag": "us-gaap:Assets",
        "totalAssetsDerived": false,
        "totalLiabilities": 285508000000,
        "totalLiabilitiesTag": "us-gaap:Liabilities",
        "totalLiabilitiesDerived": false,
        "stockholdersEquity": 73733000000,
        "stockholdersEquityTag": "us-gaap:StockholdersEquity",
        "stockholdersEquityDerived": false,
        "cash": 35934000000,
        "cashTag": "us-gaap:CashAndCashEquivalentsAtCarryingValue",
        "cashDerived": false,
        "operatingCashFlow": 111482000000,
        "operatingCashFlowTag": "us-gaap:NetCashProvidedByUsedInOperatingActivities",
        "operatingCashFlowDerived": false,
        "capitalExpenditure": 12715000000,
        "capitalExpenditureTag": "us-gaap:PaymentsToAcquirePropertyPlantAndEquipment",
        "capitalExpenditureDerived": false,
        "freeCashFlow": 98767000000,
        "freeCashFlowTag": "derived: us-gaap:NetCashProvidedByUsedInOperatingActivities minus us-gaap:PaymentsToAcquirePropertyPlantAndEquipment",
        "freeCashFlowDerived": true,
        "sharesOutstanding": 14773260000,
        "sharesOutstandingTag": "us-gaap:CommonStockSharesOutstanding",
        "sharesOutstandingDerived": false,
        "sharesOutstandingDate": "2025-09-27",
        "derivedFields": ["freeCashFlow"],
        "valueRule": "latest-filed",
        "filingIndexUrl": "https://www.sec.gov/Archives/edgar/data/320193/000032019325000079/",
        "factsUrl": "https://data.sec.gov/api/xbrl/companyfacts/CIK0000320193.json",
        "deliveredAt": "2026-10-13T15:02:13.700Z"
    },
    {
        "status": "not-found",
        "errorCode": "ticker-not-found",
        "error": "SEC's ticker list has no ticker APPL. Check the spelling, or give the company's CIK: a company that is no longer listed keeps its CIK. Not charged.",
        "mode": "companies",
        "input": "APPL",
        "cik": null,
        "ticker": "APPL",
        "revenue": null
    }
]
```

The second row is shortened here. Every row carries every field, with `null` where a value does not apply, so exports keep the same columns.

### Tips for faster runs and lower costs

- Ask for the periods you use. Quarters next to the years multiply the rows by five, and the cost with them.
- Put all your companies in one run. Each company is one download whatever the number of years, so 5 or 20 years cost the same time.
- Use CIKs for companies that changed their ticker, merged or stopped trading. SEC's ticker list holds only current listings.
- In a screen, set `minValue` or `maxResults` so you pay for the companies you will look at. The rows come sorted high to low, so `maxResults` keeps the largest.
- Pick a screen period SEC has had time to fill. The largest companies must file a 10-K within 60 days of the fiscal year end and the smallest within 90, so a calendar year screen run before April misses many companies.
- Quarterly cash flow is thin in a screen, because most companies report it only as a year to date figure and a frame holds one fact per company. Companies mode works out those quarters for you.

### FAQ, disclaimers and support

#### Is it legal to collect data from SEC EDGAR?

The XBRL figures companies file with SEC are public records, and SEC publishes them as JSON for automated use. SEC asks automated tools to declare who they are and to stay under 10 requests a second. The Actor declares itself in every request and stays under 5. How you may use what you collect depends on your purpose and your country, so check that for your use case. Take this as general information, and ask a lawyer for legal advice.

#### Is this an official SEC tool, and is it investment advice?

No to both. The Actor is an independent tool. It is not made, endorsed or checked by the U.S. Securities and Exchange Commission. The numbers come as filed: if a company tagged a figure wrongly, the row repeats it, and a derived value is only as good as the two figures behind it. Nothing in the output is investment advice or a recommendation to buy or sell anything. Check the filing on sec.gov before you act on a figure.

#### Why is a figure empty?

The company did not report it under any tag the Actor reads for that metric, or reported it only per share class or per segment. SEC's XBRL facts hold only figures without such breakdowns, so Berkshire Hathaway's EPS, reported per class, stays empty. A bank such as JPMorgan reports no gross profit, no operating income and no capital expenditure tag, so those stay empty too, along with free cash flow. A total that the company does not report is not added up from its parts, except the three derived values listed above.

#### Why does my figure differ from a finance website?

A data site may adjust figures, take them from a different line, or count a fiscal year by calendar dates. This Actor gives the figure as tagged in the filing, under the tag named in the row. Check the tag and the `valueRule` first: a split or a restatement changes the latest figure but not the first reported one.

#### How is Q4 worked out?

Companies file no 10-Q for the fourth quarter. The Actor builds Q4 from the day after Q3 ends to the fiscal year end, takes the 10-K as its filing, and uses a 3-month figure when the 10-K reports one. Otherwise each flow is the fiscal year minus the nine months to Q3, with the same tag, and is flagged as derived. Diluted EPS is never subtracted, so Q4 EPS is empty unless the 10-K reports it for the quarter.

#### Which companies are covered?

Companies that file financial statements with SEC in XBRL under US GAAP: US listed companies and foreign companies that report in US GAAP. Companies that report under IFRS, such as many foreign private issuers on Form 20-F, get a free `no-us-gaap-data` row. Funds, trusts and companies that never filed XBRL statements get a free `no-xbrl-data` row.

#### What happens when SEC limits the requests?

A "too many requests" answer (HTTP 429) is waited out, for as long as SEC's Retry-After header says and at most a minute, up to three times, and every request waits with it. A refusal (HTTP 403) gets one retry after 10 seconds. A second refusal stops all requests for the rest of the run, because SEC limits a busy address for a while. The companies the run did not reach get a `skipped` row with the code `sec-blocked`, and nothing is charged for them.

#### What happens when a run reaches its time limit?

The Actor reads the time limit of the run from the platform and starts no new download in the last 30 seconds. The companies it did not reach get a `skipped` row with the code `run-time-limit`, and nothing is charged for them. Run them again in a new run.

#### What if something looks wrong?

Open the Issues tab on the Actor page and describe your input and what you expected. A run link helps. Issues are answered within two days.

### Other Actors by the same developer

- [SEC EDGAR Filing Monitor](https://apify.com/lone_rachis/sec-edgar-filing-monitor): new SEC filings for the tickers or CIKs you watch.
- [SEC Form D Feed](https://apify.com/lone_rachis/sec-form-d-raises-feed): new private fundraising rounds filed with the SEC on Form D, with amounts and industry.
- [UK Company Check](https://apify.com/lone_rachis/uk-company-check): Companies House status, outstanding charges and risk flags for UK companies, or a list of newly registered ones.
- [US Trademark Status and Watch](https://apify.com/lone_rachis/us-trademark-status-watch): USPTO status and upcoming deadlines for US trademarks, and what changed since your last run for marks you watch.
- [New Scholarly Papers Watch](https://apify.com/lone_rachis/scholarly-papers-watch): papers new since your last run for the keywords, ORCID authors, journals, funders or DOIs you watch, from Crossref.
- [Full Page Website Screenshot](https://apify.com/lone_rachis/full-page-website-screenshot): full-page PNG or JPEG screenshots, including pages that load content as you scroll.

# Actor input Schema

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

companies: the fiscal periods of the companies listed below, one row per company and period. screen: every company that reported the first chosen metric for one calendar period, one row per company, from SEC's frames.

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

Tickers (AAPL, BRK.B) or CIKs (320193 or CIK0000320193), one per line, up to 500. A ticker is looked up in SEC's ticker list; a company that is no longer listed can still be read by its CIK. Used in companies mode.

## `periods` (type: `string`):

annual: one row per fiscal year, from the 10-K (or 20-F, 40-F). quarterly: one row per fiscal quarter, from the 10-Q, plus Q4 from the 10-K. both: the two together.

## `years` (type: `integer`):

How many of the latest fiscal years to return per company. Annual gives that many rows per company; quarterly gives four times as many. Counted from the company's latest filed period, so a company that stopped filing still returns its last years.

## `valueRule` (type: `string`):

A figure appears again in later filings as a comparative, sometimes restated. latest-filed takes the value from the newest filing that reports the period, so restatements win. first-filed takes the value as first reported.

## `metrics` (type: `array`):

The metrics to return in screen mode. The first one decides which companies are in the screen, sorts them from high to low, and is the one minValue and maxValue apply to. Each metric needs one SEC request per XBRL tag it can come from (revenue needs 6).

## `period` (type: `string`):

CY2024 for a calendar year, CY2025Q2 for a calendar quarter. SEC places each company's fiscal period in the calendar period it fits best, so a fiscal year ending in September 2024 counts as CY2024. Balances (assets, cash, shares) are read on the last day of the period. Used in screen mode.

## `minValue` (type: `number`):

Keep companies whose first metric is at least this much, in US dollars (dollars per share for diluted EPS). Leave empty for no lower limit.

## `maxValue` (type: `number`):

Keep companies whose first metric is at most this much. Leave empty for no upper limit.

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

Stop after delivering this many rows, 1,000 unless you change it. In screen mode the companies with the highest values come first; a full CY2024 revenue screen holds about 5,100 companies. Clear the field for no limit, and use Maximum cost per run to cap spending.

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

Optional. SEC asks every automated tool to name a contact in the User-Agent header of its requests. Leave it empty to use the Actor developer's address. Give your own if you want SEC to reach you about your runs. It is sent to SEC only, in that header, and is not stored in the output.

## Actor input object example

```json
{
  "mode": "companies",
  "companies": [
    "AAPL",
    "MSFT",
    "JPM"
  ],
  "periods": "annual",
  "years": 3,
  "valueRule": "latest-filed",
  "metrics": [
    "revenue"
  ],
  "period": "CY2024",
  "maxResults": 1000
}
```

# Actor output Schema

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

Dataset with one row per company and period: status, company, fiscal period, form and filing date, thirteen metrics with the XBRL tag and a derived flag next to each, and links to the filing and the source file.

## `summary` (type: `string`):

Counts of companies or frames read, rows delivered and charged, rows not found, without data or failed, the requests and bytes read from SEC and the run time.

# 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",
        "JPM"
    ],
    "years": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("lone_rachis/sec-xbrl-fundamentals").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",
        "JPM",
    ],
    "years": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("lone_rachis/sec-xbrl-fundamentals").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",
    "JPM"
  ],
  "years": 3
}' |
apify call lone_rachis/sec-xbrl-fundamentals --silent --output-dataset

```

## MCP server setup

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

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/dcD4T7SfswaivlguQ/builds/KyH5SkMiFZNY63y1c/openapi.json
