DEV Community

Michalis Solomou
Michalis Solomou

Posted on

How to Track SEC Form D Filings in Real Time

If you sell to startups — SaaS tools, recruiting, PR, dev shops, anything B2B — the moment a company raises funding is one of the best buying-intent signals you'll ever get. Fresh budget, new headcount plans, a founder actively looking for vendors. The problem is that funding announcements (TechCrunch, press releases) lag the actual event by days or weeks.

The underlying event is public before the press writes about it: a Form D filing with the SEC. Here's how to pull it yourself.

What is a Form D?

Form D is the filing a company makes with the SEC when it raises money in a private offering (the overwhelming majority of VC/angel rounds in the US). It's short, structured, and — unlike an 8-K or 10-K — filed within 15 days of the first sale of securities, often well before any public announcement. It includes:

  • Company name, address, and industry (primarySICCode)
  • Amount raised (totalOfferingAmount)
  • Date of first sale
  • Related persons (executives, sometimes directors)

All of it is public, free, and structured XML.

Where the data lives

SEC EDGAR exposes two useful surfaces:

  1. Full-text search APIhttps://efts.sec.gov/LATEST/search-index?q=...&forms=D lets you query recent Form D filings.
  2. The daily/quarterly index fileshttps://www.sec.gov/Archives/edgar/full-index/ list every filing by date, which you can filter to form.idx entries starting with D.
  3. Per-filing XML — each Form D filing has a primary_doc.xml with the structured data above, at a predictable URL once you have the accession number.

A minimal polling script

import requests
import time

HEADERS = {"User-Agent": "YourCompany research@yourcompany.com"}  # SEC requires this

def get_recent_form_d(days_back=1):
    url = "https://www.sec.gov/cgi-bin/browse-edgar"
    params = {
        "action": "getcompany",
        "type": "D",
        "dateb": "",
        "owner": "include",
        "count": "100",
        "output": "atom",
    }
    resp = requests.get(url, params=params, headers=HEADERS)
    resp.raise_for_status()
    return resp.text  # parse the Atom feed for entries

def poll_loop():
    while True:
        feed = get_recent_form_d()
        # parse feed, diff against last-seen accession numbers, fetch primary_doc.xml
        # for each new filing, extract company name / amount / industry
        time.sleep(60 * 15)  # SEC rate limit: stay well under 10 req/sec, this is generous
Enter fullscreen mode Exit fullscreen mode

The full-text search endpoint (efts.sec.gov) is faster to filter by form type and date range if you want something closer to real time than the daily index files, which only update once EDGAR finishes processing the day's batch.

Things that bite people building this

  • Rate limits. SEC asks for a descriptive User-Agent header and caps you around 10 requests/second — polling every filing individually will get you blocked fast. Batch via the index files where you can.
  • Amount parsing. totalOfferingAmount is sometimes "Indefinite" — handle it, don't crash your parser on it.
  • Deduplication. Companies amend Form D filings (Form D/A). Decide up front whether you want the latest amendment or the original filing as your "signal" — they can have meaningfully different amounts.
  • Industry codes. SIC codes are coarse and sometimes wrong/generic ("Other Technology" when the company is clearly biotech, for example) — don't rely on them alone if you need clean industry categorization.
  • No contact info. Form D gives you the company and sometimes executive names — it does not give you emails or phone numbers. That's a separate enrichment step, and one worth doing carefully — see the compliance note below.

A note on compliance

Form D is public record, so scraping it is fine. Be careful with what you build on top of it: don't scrape personal emails, don't skip an unsubscribe/opt-out mechanism if you're sending outreach off this signal, and keep enrichment to company-level data (domain, generic role emails) rather than harvesting personal information you don't have a lawful basis to hold.

If you'd rather not build the pipeline

I built exactly this — a daily-updating feed of companies that just filed a Form D (plus funding-news signals), scored 0–100 as sales leads, with company domain and generic contact emails attached. Free tier, no card required: fundingsignals.net

But if you just need the raw filings for your own pipeline, everything above is enough to get you a working poller in an afternoon.

Top comments (0)