DEV Community

linderroger-eng
linderroger-eng

Posted on

Track Insider Trading in Real Time with This Free SEC EDGAR API

Track Insider Trading in Real Time with This Free SEC EDGAR API

When corporate insiders — CEOs, CFOs, board members, and major shareholders — buy or sell their own company's stock, they're required by law to disclose it. These disclosures, filed with the SEC as Form 4, are some of the most valuable signals in public finance. And now, with the SEC EDGAR API, you can access them programmatically — for free.

In this guide, we'll walk through how to use the SEC EDGAR API to track insider trades in real time, build a Python-based monitoring script, and understand why insider buying is one of the most reliable bullish signals in investing.


Why Insider Trading Data Matters

Let's be clear: we're talking about legal insider trading — the kind that gets disclosed to the SEC within two business days of the transaction. When a company's CEO goes out and buys $2 million worth of their own stock on the open market, that's a statement. They're putting their own money where their mouth is.

Here's why insider buying is considered a bullish signal:

  • Information asymmetry: Insiders know the company's pipeline, contracts, and financials better than anyone. When they buy, they believe the stock is undervalued.
  • No obligation to buy: Unlike selling (which can happen for many reasons — diversification, taxes, liquidity), buying is almost always a deliberate vote of confidence.
  • Cluster buying: When multiple insiders at the same company buy stock within a short window, it's an even stronger signal.
  • Track record: Academic research (including studies by Seyhun, Lakonishok, and Lee) consistently shows that insider purchases outperform the market by 5–10% over the following 12 months.

The challenge has always been accessing this data in a usable form. The SEC EDGAR system is a treasure trove, but parsing raw SGML filings isn't fun. That's where this API comes in.


Introducing the SEC EDGAR API

The SEC EDGAR API wraps the raw SEC filing data into clean, structured JSON endpoints. You can query for:

  • Form 4 filings (insider trades)
  • Company filings (10-K, 10-Q, 8-K, etc.)
  • CIK lookups (find any company's SEC identifier)
  • Financial statements

The base URL is: https://sec-edgar-api-0nxw.onrender.com

And best of all — there's a free tier that lets you get started without a credit card.


Getting Started: Your First API Call

Let's start simple. Here's how to pull recent insider trades using curl:

curl -X GET "https://sec-edgar-api-0nxw.onrender.com/insider-trades?limit=10" \
  -H "Accept: application/json"
Enter fullscreen mode Exit fullscreen mode

This returns the 10 most recent Form 4 filings across all companies. The response looks something like this:

{
  "trades": [
    {
      "filer_name": "SMITH JOHN R",
      "filer_title": "Chief Executive Officer",
      "company_name": "Acme Corp",
      "ticker": "ACME",
      "transaction_date": "2025-05-28",
      "transaction_type": "P",
      "shares": 50000,
      "price_per_share": 42.15,
      "total_value": 2107500,
      "shares_owned_after": 250000,
      "filing_date": "2025-05-30"
    }
  ],
  "total": 1,
  "page": 1
}
Enter fullscreen mode Exit fullscreen mode

The transaction_type field uses SEC codes:

  • P = Purchase (open market buy) ✅ Bullish
  • S = Sale (open market sell)
  • A = Award (granted shares, options)
  • D = Disposition

Filtering by Company or Ticker

Want to track insider activity for a specific company? Just add a ticker parameter:

curl -X GET "https://sec-edgar-api-0nxw.onrender.com/insider-trades?ticker=AAPL&limit=20" \
  -H "Accept: application/json"
Enter fullscreen mode Exit fullscreen mode

Or filter by transaction type to see only purchases:

curl -X GET "https://sec-edgar-api-0nxw.onrender.com/insider-trades?transaction_type=P&limit=50" \
  -H "Accept: application/json"
Enter fullscreen mode Exit fullscreen mode

Filter by minimum transaction value (e.g., trades over $500,000):

curl -X GET "https://sec-edgar-api-0nxw.onrender.com/insider-trades?min_value=500000&transaction_type=P" \
  -H "Accept: application/json"
Enter fullscreen mode Exit fullscreen mode

Building a Python Insider Trade Monitor

Now let's build something actually useful — a Python script that polls the API and alerts you when significant insider buying occurs.

import requests
import time
from datetime import datetime, timedelta

# Configuration
BASE_URL = "https://sec-edgar-api-0nxw.onrender.com"
API_KEY = "your_api_key_here"  # Get yours from RapidAPI
MIN_PURCHASE_VALUE = 100_000   # Alert on buys > $100k
WATCH_TICKERS = ["AAPL", "MSFT", "NVDA", "TSLA"]  # Optional: specific watchlist

def get_insider_trades(ticker=None, transaction_type="P", days_back=7, limit=50):
    """
    Fetch recent insider trades from the SEC EDGAR API.

    Args:
        ticker: Optional stock ticker to filter by
        transaction_type: 'P' for purchases, 'S' for sales
        days_back: How many days to look back
        limit: Max number of results

    Returns:
        List of trade dictionaries
    """
    endpoint = f"{BASE_URL}/insider-trades"

    params = {
        "transaction_type": transaction_type,
        "limit": limit,
        "days_back": days_back
    }

    if ticker:
        params["ticker"] = ticker

    headers = {
        "Accept": "application/json",
        "x-api-key": API_KEY
    }

    response = requests.get(endpoint, params=params, headers=headers)
    response.raise_for_status()

    data = response.json()
    return data.get("trades", [])


def find_cluster_buying(days_back=30, min_insiders=3):
    """
    Find companies where multiple insiders are buying — the strongest signal.

    Args:
        days_back: Look-back window in days
        min_insiders: Minimum number of distinct insiders buying

    Returns:
        Dictionary of {ticker: [trades]} for cluster buys
    """
    trades = get_insider_trades(transaction_type="P", days_back=days_back, limit=200)

    # Group by ticker
    by_ticker = {}
    for trade in trades:
        ticker = trade.get("ticker", "UNKNOWN")
        if ticker not in by_ticker:
            by_ticker[ticker] = []
        by_ticker[ticker].append(trade)

    # Filter for cluster buying
    clusters = {
        ticker: trade_list
        for ticker, trade_list in by_ticker.items()
        if len(set(t["filer_name"] for t in trade_list)) >= min_insiders
    }

    return clusters


def calculate_signal_strength(trades):
    """
    Score insider buying signal strength based on:
    - Number of distinct insiders buying
    - Seniority of insiders (CEO/CFO weighted higher)
    - Total dollar value of purchases
    - Recent concentration (how recent the buys are)
    """
    if not trades:
        return 0

    score = 0
    senior_titles = {"chief executive officer", "ceo", "chief financial officer", 
                     "cfo", "president", "chairman", "director"}

    insiders = set()
    total_value = 0

    for trade in trades:
        filer = trade.get("filer_name", "")
        title = trade.get("filer_title", "").lower()
        value = trade.get("total_value", 0)

        insiders.add(filer)
        total_value += value

        # Bonus points for senior executives
        if any(t in title for t in senior_titles):
            score += 3
        else:
            score += 1

    # Scale by number of distinct insiders
    score += len(insiders) * 2

    # Scale by total dollar amount (logarithmic)
    if total_value > 0:
        import math
        score += math.log10(total_value)

    return round(score, 2)


def monitor_insider_buying(check_interval_minutes=60):
    """
    Continuously monitor for significant insider buying and print alerts.
    """
    print(f"🔍 Starting insider trade monitor...")
    print(f"   Min purchase alert: ${MIN_PURCHASE_VALUE:,}")
    print(f"   Check interval: every {check_interval_minutes} minutes\n")

    seen_filings = set()

    while True:
        print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M')}] Checking for new insider purchases...")

        try:
            trades = get_insider_trades(transaction_type="P", days_back=2, limit=100)

            new_significant = []
            for trade in trades:
                filing_key = f"{trade.get('ticker')}_{trade.get('filer_name')}_{trade.get('transaction_date')}"

                if filing_key in seen_filings:
                    continue

                seen_filings.add(filing_key)
                value = trade.get("total_value", 0)

                if value >= MIN_PURCHASE_VALUE:
                    new_significant.append(trade)

            if new_significant:
                print(f"\n🚨 SIGNIFICANT INSIDER PURCHASES DETECTED:\n")
                for trade in sorted(new_significant, key=lambda x: x.get("total_value", 0), reverse=True):
                    print(f"  📈 {trade['ticker']}{trade['company_name']}")
                    print(f"     Insider: {trade['filer_name']} ({trade['filer_title']})")
                    print(f"     Purchased: {trade['shares']:,} shares @ ${trade['price_per_share']:.2f}")
                    print(f"     Total Value: ${trade['total_value']:,.0f}")
                    print(f"     Filed: {trade['filing_date']}\n")
            else:
                print("   No new significant purchases found.")

        except requests.RequestException as e:
            print(f"   API error: {e}")

        # Check for cluster buying weekly
        print("\n📊 Checking for cluster buying patterns...")
        clusters = find_cluster_buying(days_back=30, min_insiders=3)

        if clusters:
            print(f"   Found cluster buying in {len(clusters)} companies:")
            for ticker, cluster_trades in clusters.items():
                strength = calculate_signal_strength(cluster_trades)
                total = sum(t.get("total_value", 0) for t in cluster_trades)
                print(f"   🔥 {ticker}: {len(cluster_trades)} purchases, ${total:,.0f} total (signal: {strength})")

        print(f"\nNext check in {check_interval_minutes} minutes...\n")
        time.sleep(check_interval_minutes * 60)


if __name__ == "__main__":
    # Quick demo — get top 10 largest insider purchases this week
    print("Top 10 Largest Insider Purchases (Last 7 Days):\n")
    trades = get_insider_trades(transaction_type="P", days_back=7, limit=100)

    # Sort by total value
    trades.sort(key=lambda x: x.get("total_value", 0), reverse=True)

    for i, trade in enumerate(trades[:10], 1):
        print(f"{i}. {trade.get('ticker', 'N/A')}{trade.get('company_name', 'N/A')}")
        print(f"   {trade.get('filer_title', 'N/A')}: {trade.get('filer_name', 'N/A')}")
        print(f"   {trade.get('shares', 0):,} shares @ ${trade.get('price_per_share', 0):.2f} = ${trade.get('total_value', 0):,.0f}\n")

    # Find cluster buys
    print("\nCluster Buying (3+ Insiders, Last 30 Days):")
    clusters = find_cluster_buying()
    for ticker, cluster_trades in clusters.items():
        print(f"  {ticker}: {len(cluster_trades)} insider purchases")
Enter fullscreen mode Exit fullscreen mode

Real-World Use Cases

Here are some practical ways to use this data:

1. Pre-Earnings Insider Scan
Run a scan 30–60 days before earnings season. Significant insider buying before earnings often signals management confidence in the upcoming results.

2. Sector Rotation Detection
If you see cluster buying across multiple companies in the same sector (e.g., energy or biotech), it might signal a sector-wide catalyst that insiders are aware of.

3. Turnaround Plays
Look for insider buying in beaten-down stocks. When executives buy shares after a significant selloff, it often marks a bottom.

4. Short Squeeze Setup Screener
Combine insider buying data with high short interest stocks. When heavily shorted companies start showing significant insider purchases, it can be a powerful counter-signal.


API Tiers and Rate Limits

The SEC EDGAR API offers a free tier that lets you:

  • Make up to 100 requests per month at no cost
  • Access all core endpoints including /insider-trades
  • No credit card required to get started

For more serious use cases — running a monitor script, powering a dashboard, or building a fintech app — paid tiers offer higher rate limits and additional endpoints.


Getting Your API Key

The SEC EDGAR API is available on RapidAPI. Search for "SEC EDGAR API by linderroger" on RapidAPI to find the listing, subscribe to the free tier, and grab your API key.

Once you have it, replace your_api_key_here in the Python code above with your actual key, and you're live.


What to Look for in the Data

Not all insider buying is equally meaningful. Here's a quick cheat sheet:

Higher-signal purchases:

  • CEO or CFO buying on the open market
  • Large dollar amounts (>$500K personally)
  • Multiple insiders buying within the same 2-week window
  • Buying after a significant stock decline
  • Insiders haven't sold in the past year

Lower-signal purchases:

  • Purchases from stock option exercises (marked M or A)
  • Very small amounts relative to insider's known wealth
  • Automatic/programmatic purchasing plans (Rule 10b5-1)

Conclusion

Insider trading data is one of the few legal edges available to retail investors. It's public information, disclosed within 48 hours, and tells you exactly what the people with the most information about a company are doing with their own money.

With the SEC EDGAR API, you can access this data programmatically, build custom screens, and potentially catch big moves before they happen.

Ready to get started? Search for "SEC EDGAR API by linderroger" on RapidAPI and start your free tier today. The free plan gives you 100 requests/month — more than enough to build a functional insider trade monitor and see real value before upgrading.

Happy trading. 📈

Top comments (0)