Over the last 90 days, 9,951 earnings calls landed in the archive I work on. Laid end to end that's about 380 million characters of transcript text — call it 60 million words. At a fast reading speed of 250 words per minute, working an eight-hour day with no meetings, no lunch and no weekends, you would need about two years to read one quarter of earnings season. By then, eight more quarters would have arrived.
On the single busiest day this spring — May 6, 2026 — 877 companies held earnings calls. One day. That's around five and a half million words of new transcript before dinner.
I think about these numbers a lot, because my job is maintaining a corpus of 247,000+ earnings call transcripts from 12,692 companies, split into 11.7 million speaker segments, going back to January 2020. Nobody reads that. Nobody ever will. And once you accept that reading is off the table, the interesting question becomes: what does it mean to know what was said in earnings season?
What breaks at scale
Treating earnings calls as a dataset sounds clean until you actually build the dataset. A few things I've learned the hard way:
Tickers are not unique. ALV is Autoliv in the US, Allianz in Germany and Alvopetro in Canada. AIR is AAR Corp, Airbus and Air New Zealand. A customer once audited our US coverage and found dozens of symbols shared by multiple companies across venues. If your pipeline joins on the bare ticker, you are quietly blending an airbag manufacturer into an insurance giant's history. Everything downstream — sentiment, mention counts, comparisons — inherits the contamination, and no single-call reader would ever notice.
M&A calls file under the acquirer. Search for Equifax and you'll find calls that are mostly about Kount, Appriss and Boa Vista — acquisition calls, indexed under the buyer's ticker, with the target's name all over the transcript. A naive "all EFX calls" query is not the dataset you think it is.
The metadata lies in small ways. The same venue appears as "New York Stock Exchange" in some records and "NYSE" in others. The same company's ticker is stored bare in one row and exchange-suffixed (NVDA vs NVDA:US) in another. Every one of these inconsistencies is invisible at reading scale and fatal at query scale. Most of the engineering work in a corpus like this isn't ingestion — it's canonicalization.
I'm not sharing these as war stories. They're the reason "just scrape some transcripts" demos fall apart the first time someone runs a real cross-company question against them.
What becomes possible
Here's the trade. You give up the idea of reading everything, and in return you get to ask questions that reading could never answer:
- How many companies mentioned a theme this quarter, versus the last eight? One request against a by-ticker search endpoint, and you have narrative velocity as a time series. I ran exactly this for "agentic AI" — the full curve is here — and it surfaced a first mention from May 2023 that no human reading plan would have caught.
- Are analysts converging on a question? When two regional banks get asked the same deposit-pricing question in the same week, that's a consensus risk forming in real time. You catch it by querying analyst segments across companies, which is precisely what speaker-level structure exists for — 11.7 million segments, each tagged executive, analyst or operator.
- Which three calls should I actually read? This is the part people miss. Querying doesn't replace reading; it aims it. A cross-sectional query turns 9,951 candidate calls into the three where something genuinely changed — and those three absolutely deserve a slow, human read.
The uncomfortable truth about earnings season is that the reading-based workflow was never complete; it was just complete-feeling. An analyst covering 20 names read 20 calls and called it coverage, while 9,931 other companies talked about the same suppliers, the same customers and the same risks. The information was always there. It just wasn't reachable.
Now it's a GET request.
The corpus: 247,000+ transcripts, 12,692 companies, 11.7M speaker segments, updated as calls happen — API and docs here.