<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: arigatouapps</title>
    <description>The latest articles on DEV Community by arigatouapps (@arigatouapps).</description>
    <link>https://dev.to/arigatouapps</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4036578%2F70c803a4-a3f2-450c-937c-42ab41010098.png</url>
      <title>DEV Community: arigatouapps</title>
      <link>https://dev.to/arigatouapps</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arigatouapps"/>
    <language>en</language>
    <item>
      <title>Get free US-stock fundamentals from the SEC EDGAR API (and build a "divergence score")</title>
      <dc:creator>arigatouapps</dc:creator>
      <pubDate>Sun, 19 Jul 2026 14:25:10 +0000</pubDate>
      <link>https://dev.to/arigatouapps/get-free-us-stock-fundamentals-from-the-sec-edgar-api-and-build-a-divergence-score-44d4</link>
      <guid>https://dev.to/arigatouapps/get-free-us-stock-fundamentals-from-the-sec-edgar-api-and-build-a-divergence-score-44d4</guid>
      <description>&lt;p&gt;You want &lt;strong&gt;revenue, net income, and EPS&lt;/strong&gt; for US stocks — free, no API key, no flaky scraping. Good news: the SEC hands you the actual filings in machine-readable form via the &lt;strong&gt;EDGAR &lt;code&gt;companyfacts&lt;/code&gt; API&lt;/strong&gt;. Here's how to pull fundamentals, the gotchas that will bite you, and how to turn it into a simple "is this stock rich or cheap?" signal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why SEC EDGAR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Official, primary source&lt;/strong&gt; — the exact 10-K (annual) / 10-Q (quarterly) filings. Accurate numbers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No key, free, commercial-ok&lt;/strong&gt; — generous rate limits (you must send a descriptive &lt;code&gt;User-Agent&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured&lt;/strong&gt; — XBRL tags (US-GAAP) let you pull "revenue", "net income", etc. by concept name.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prices aren't in EDGAR, so pair it with a price source (stooq, Yahoo-style feeds, etc.).&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Resolve the CIK
&lt;/h2&gt;

&lt;p&gt;EDGAR keys companies by &lt;strong&gt;CIK&lt;/strong&gt; (a serial ID), not ticker. Grab the mapping:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"User-Agent: your-app your@email"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://www.sec.gov/files/company_tickers.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look up your ticker, then zero-pad the CIK to 10 digits (&lt;code&gt;320193&lt;/code&gt; → &lt;code&gt;0000320193&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Pull companyfacts
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"User-Agent: your-app your@email"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://data.sec.gov/api/xbrl/companyfacts/CIK0000320193.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under &lt;code&gt;facts."us-gaap"&lt;/code&gt; you get a time series per concept. The useful ones:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;us-gaap tag&lt;/th&gt;
&lt;th&gt;meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Revenues&lt;/code&gt; / &lt;code&gt;RevenueFromContractWithCustomerExcludingAssessedTax&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;revenue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NetIncomeLoss&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;net income&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EarningsPerShareDiluted&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;diluted EPS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GrossProfit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;gross profit&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each value sits in &lt;code&gt;units.USD&lt;/code&gt; (or &lt;code&gt;USD/shares&lt;/code&gt; for EPS) with &lt;code&gt;start&lt;/code&gt;/&lt;code&gt;end&lt;/code&gt; (period), &lt;code&gt;fp&lt;/code&gt; (Q1–FY), &lt;code&gt;form&lt;/code&gt; (10-K/10-Q), and &lt;code&gt;fy&lt;/code&gt;. &lt;strong&gt;Different companies use different tags for the same thing&lt;/strong&gt; (some report &lt;code&gt;Revenues&lt;/code&gt;, others &lt;code&gt;RevenueFromContractWithCustomer…&lt;/code&gt;), so try a &lt;strong&gt;prioritized list of candidate tags&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CANDIDATES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;revenue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RevenueFromContractWithCustomerExcludingAssessedTax&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Revenues&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SalesRevenueNet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;netIncome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NetIncomeLoss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;epsDiluted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EarningsPerShareDiluted&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;facts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;USD&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;facts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;us-gaap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]?.[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;units&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="nx"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Gotchas (this is the real work)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ① Quarterly values are year-to-date — diff them
&lt;/h3&gt;

&lt;p&gt;10-Q revenue is often reported &lt;strong&gt;cumulatively (YTD)&lt;/strong&gt;, not as a standalone quarter. To get Q3's three months: &lt;code&gt;Q3 YTD − Q2 YTD&lt;/code&gt;. Q1 is as-is; Q4 = &lt;code&gt;annual (10-K) − sum(Q1..Q3)&lt;/code&gt;. Naively summing YTD figures &lt;strong&gt;double-counts&lt;/strong&gt; and doubles your revenue.&lt;/p&gt;

&lt;h3&gt;
  
  
  ② Splits make EPS and price jump
&lt;/h3&gt;

&lt;p&gt;Historical EPS and price show step changes around splits. For time-series comparison you need split adjustment (using adjusted-close on the price side is the easy path).&lt;/p&gt;

&lt;h3&gt;
  
  
  ③ US-GAAP only → foreign filers are missing
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;companyfacts&lt;/code&gt; &lt;code&gt;us-gaap&lt;/code&gt; covers US-basis filers (10-K/10-Q). &lt;strong&gt;Foreign companies file 20-F / IFRS&lt;/strong&gt; and won't appear here. "Why can't I get TSM or ASML?" — that's why.&lt;/p&gt;

&lt;h3&gt;
  
  
  ④ Use TTM
&lt;/h3&gt;

&lt;p&gt;Quarters are seasonal, so for P/E and P/S use &lt;strong&gt;trailing-twelve-months&lt;/strong&gt; (sum of the last 4 quarters).&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Combine with price → a "divergence score"
&lt;/h2&gt;

&lt;p&gt;Once you have fundamentals (the reality) and price (the expectation), a fun signal falls out. I use &lt;strong&gt;divergence = price CAGR − revenue CAGR&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;divergence = CAGR(price) − CAGR(revenue)
  CAGR(x) = (x_end / x_start) ** (1 / years) − 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;price growing faster than revenue → &lt;strong&gt;expectations have run ahead of the business&lt;/strong&gt; (rich-leaning)&lt;/li&gt;
&lt;li&gt;the reverse → &lt;strong&gt;the business is outpacing the price&lt;/strong&gt; (cheap-leaning)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Layer in &lt;strong&gt;P/E and P/S versus each stock's own historical range&lt;/strong&gt; (median, 25–75% band) and you get a neutral "is this high or low &lt;em&gt;for this stock&lt;/em&gt;?" read that's harder to misread than an absolute P/E.&lt;/p&gt;

&lt;h2&gt;
  
  
  A worked example
&lt;/h2&gt;

&lt;p&gt;I built a free visualizer around exactly this — &lt;a href="https://stocks.arigatouapps.com/?lang=en" rel="noopener noreferrer"&gt;kabu&lt;/a&gt; — that shows the price-vs-fundamentals gap for US stocks using only EDGAR + prices (e.g. the &lt;a href="https://stocks.arigatouapps.com/verdict/nvda" rel="noopener noreferrer"&gt;NVDA read&lt;/a&gt;). It's Japanese-first with an English UI, and it gives no investment advice — just a neutral, sourced visualization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;US-stock fundamentals are &lt;strong&gt;free and official&lt;/strong&gt; via SEC EDGAR &lt;code&gt;companyfacts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The gotchas that matter: &lt;strong&gt;quarterly = YTD diff / split adjustment / US-GAAP only (no foreign) / TTM&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Pair with price for a &lt;strong&gt;divergence score&lt;/strong&gt; to see expectation vs reality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start with one ticker: hit &lt;code&gt;companyfacts&lt;/code&gt;, list &lt;code&gt;Revenues&lt;/code&gt;, and plot it. The rest is bookkeeping.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Based on public SEC filings and public prices. This post (and the tool mentioned) is for information/education, not investment advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>finance</category>
      <category>api</category>
      <category>javascript</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
