Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Query and analyze SEC filings and financial statements using EdgarTools. Get company data, filings, XBRL financials, and perform multi-company analysis.
.claude/skills/microck-edgartools/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 169% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 236% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 117% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 230% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 135% | 0% |
Analyze SEC filings and financial statements using EdgarTools
Essential SEC filing analysis operations. See objects.md for object reference, workflows.md for patterns, readme.md for setup.
REQUIRED: Set your identity (SEC requirement):
pythonfrom edgar import set_identity set_identity("Your Name your@email.com")
Without this, all API calls fail with "User-Agent identity is not set" error.
ALWAYS use .to_context() first for concise summaries with available actions. 5-10x more token-efficient than full objects.
pythonfrom edgar import Company company = Company("AAPL") print(company.to_context()) # ~88 tokens vs 200+ for full object
Output:
**Company:** Apple Inc.
**CIK:** 0000320193
**Ticker:** AAPL
**Exchange:** Nasdaq
**Industry:** Electronic Computers (SIC 3571)
**Fiscal Year End:** Sep 30pythonfilings = company.get_filings(form="10-K") print(filings.to_context()) # ~95 tokens vs 500-1000 for rich table
Shows summary + AVAILABLE ACTIONS.
pythonfiling = filings.latest() print(filing.to_context()) # ~109 tokens, includes available methods
pythonxbrl = filing.xbrl() print(xbrl.to_context()) # ~275 tokens vs 2,500+ for full statements
Token Comparison:
| Object | Full Output | to_context() | Savings | |--------|-------------|--------------|---------| | Company | ~200 tokens | ~88 tokens | 56% | | Filings | ~500-1000 | ~95 tokens | 80-90% | | XBRL | ~2,500 tokens | ~275 tokens | 89% |
Pattern: to_context() first → see available → access data.
Common starting patterns. Use .to_context() for efficiency.
pythonfrom edgar import set_identity, Company set_identity("Your Name your@email.com") # Required first! company = Company("AAPL") print(company.to_context()) # Concise profile (~88 tokens) # OR for full details: # print(company) # Full object (~200 tokens)
pythonfrom edgar import get_current_filings filings = get_current_filings() # Last ~24 hours print(filings.to_context()) # Summary + available actions (~95 tokens) # OR to see first 5 in table: # print(filings.head(5)) # Rich table (~500-1000 tokens)
pythonfrom edgar import Company company = Company("AAPL") income = company.income_statement(periods=3) # 3 fiscal years print(income) # Full statement
Main API functions and approaches.
Choose the approach based on your use case:
When to use: Cross-company screening, pattern discovery, historical research, don't know which specific companies.
Data source: SEC quarterly indexes (updated nightly)
pythonfrom edgar import get_filings # Get all filings for a quarter filings = get_filings(2023, 1) # Q1 2023 # Filter by form type filings = get_filings(2023, 1, form="10-K") # Filter by date range filings = get_filings(2023, 1, filing_date="2023-02-01:2023-02-15") # Further filter results filtered = filings.filter(ticker="AAPL") tech_filings = filings.filter(ticker=["AAPL", "MSFT", "GOOGL"])
When to use: Monitoring recent filing activity, tracking latest submissions
Data source: SEC RSS feed (last ~24 hours)
pythonfrom edgar import get_current_filings # Get all recent filings current = get_current_filings() # Filter by form type reports = current.filter(form=["10-K", "10-Q"]) # Filter by specific companies tech_current = current.filter(ticker=["AAPL", "MSFT"])
When to use: You know the specific company ticker or name
Data source: SEC company submissions endpoint
pythonfrom edgar import Company company = Company("AAPL") # Get all filings all_filings = company.get_filings() # Filter by form type annual_reports = company.get_filings(form="10-K") # Filter by year filings_2023 = company.get_filings(year=2023) # Combine filters q1_2023_10q = company.get_filings(year=2023, form="10-Q")
When to use: Comparing multiple periods, trend analysis (fastest approach)
Data source: SEC Company Facts API
Advantages: Very fast (single API call), pre-aggregated data, multi-period comparison built-in
pythonfrom edgar import Company company = Company("AAPL") # Annual data (fiscal years) income = company.income_statement(periods=3) # Last 3 fiscal years balance = company.balance_sheet(periods=3) cash_flow = company.cash_flow_statement(periods=3) # Quarterly data quarterly_income = company.income_statement(periods=4, annual=False) # Last 4 quarters
When to use: Need specific filing details, want complete line items, analyzing single period
Data source: XBRL files attached to specific filings
Advantages: Most comprehensive detail, all line items available, exact as-filed data
pythonfrom edgar import Company company = Company("AAPL") # Get specific filing filing = company.get_filings(form="10-K")[0] # Latest 10-K # Parse XBRL xbrl = filing.xbrl() # Get statements income = xbrl.statements.income_statement() balance = xbrl.statements.balance_sheet() cash_flow = xbrl.statements.cash_flow_statement() # Access metadata print(f"Entity: {xbrl.entity_name}") print(f"Fiscal Year: {xbrl.fiscal_year}") print(f"Period: {xbrl.fiscal_period}")
⚠️ IMPORTANT: Filing has TWO different search methods. Use the right one!
filing.search(query) ⭐ Find Text in FilingsSearch the actual filing document - find keywords, topics, or sections within SEC filings.
pythonfrom edgar import Company company = Company("AAPL") filing = company.get_filings(form="DEF 14A")[0] # Proxy statement # Search for content IN the filing results = filing.search("executive compensation") # Process results print(f"Found {len(results)} matches") for match in results[:5]: # Top 5 matches print(f"Relevance score: {match.score:.2f}") print(f"Excerpt: {str(match)[:200]}...") print()
Features: BM25 relevance ranking (best matches first), searches parsed HTML sections, returns DocSection objects with scores, index cached for performance (~1-2 seconds per filing)
Use cases: Find mentions of specific topics ("revenue recognition", "risk factors"), locate sections in large filings, screen filings for relevant content, extract context around keywords
Example: Find proxy statements mentioning compensation changes
pythonfrom edgar import get_filings from datetime import datetime, timedelta # Get recent proxy statements start_date = datetime.now() - timedelta(days=30) filings = get_filings(form="DEF 14A") recent = filings.filter(filing_date=f"{start_date.strftime('%Y-%m-%d')}:") # Search each filing companies_with_matches = [] for filing in recent: matches = filing.search("executive compensation changes") if matches and len(matches) > 0: companies_with_matches.append({ 'company': filing.company, 'date': filing.filing_date, 'matches': len(matches), 'top_score': matches[0].score, 'excerpt': str(matches[0])[:200] }) print(f"Found {len(companies_with_matches)} companies")
filing.docs.search(query) 📚 Find MethodsSearch the Filing API documentation - discover how to use the Filing class.
python# Find how to use Filing API help_text = filing.docs.search("how to get XBRL") print(help_text) # Shows documentation about filing.xbrl() method help_text = filing.docs.search("convert to markdown") print(help_text) # Shows documentation about filing.markdown() method
Use cases:
| What are you searching? | Method | Returns | |-------------------------|--------|---------| | Text in the filing (content) | filing.search("keyword") | List of DocSection matches with scores | | How to use Filing API (methods) | filing.docs.search("how to") | API documentation snippets |
⚠️ Common Mistake:
python# WRONG - Searches API docs, not filing content! matches = filing.docs.search("executive compensation") # ❌ # Returns empty - API docs don't mention "executive compensation" # CORRECT - Searches the actual filing document matches = filing.search("executive compensation") # ✅ # Returns 50+ matches from proxy statement
Complete examples in common-questions.md.
| Task | Primary Method | Example | |------|----------------|---------| | Show S-1 filings from date range | get_filings(year, quarter, form="S-1", filing_date="...") | See example | | Get today's filings | get_current_filings() | See example | | Get company revenue trend | company.income_statement(periods=3) | See example | | Get quarterly financials | company.income_statement(periods=4, annual=False) | See example | | Get statement from specific filing | filing.xbrl().statements.income_statement() | See example | | Compare multiple companies | compare_companies_revenue(["AAPL", "MSFT"]) | See example | | Get latest quarterly balance sheet | company.get_filings(form="10-Q")[0].xbrl() | See example | | Get insider transactions (Form 4) | company.get_filings(form="4") | See example | | Filter filings efficiently | filings.filter(ticker="AAPL", filing_date="2024-01-01:") | See example | | Look up form types | describe_form("C") or see form-types-reference.md | See example |
Pattern: For any question, check common-questions.md for full working examples.
Advanced patterns, helpers, error handling, skill exportation: advanced-guide.md.
Includes:
Error:
RuntimeError: User-Agent identity is not set. Please call set_identity() first.Cause: Missing set_identity() call (SEC requirement)
Solution:
pythonfrom edgar import set_identity set_identity("Your Name your@email.com") # Must call before any API operations
Error:
AttributeError: 'Company' object has no attribute 'sic_code'Cause: Incorrect attribute name
Solution: Check the API reference in objects.md for correct attribute names (e.g., use company.sic instead of company.sic_code)
Cause: Not using .to_context() method
Solution: Always call .to_context() before printing full objects:
python# Instead of: print(company) # 200+ tokens # Use: print(company.to_context()) # ~88 tokens
Problem: get_filings() returns empty list
Possible causes: No filings match criteria (try broader search), wrong quarter/year combination, or form type doesn't exist for that period
Solution:
pythonfilings = get_filings(2024, 1, form="10-K") if len(filings) == 0: print("No filings found - try different criteria") # Try broader search all_filings = get_filings(2024, 1) print(f"Found {len(all_filings)} total filings in 2024 Q1")
Use the skill API to read documentation:
pythonfrom edgar.ai import get_skill skill = get_skill("EdgarTools") common_questions = skill.get_document_content("common-questions") advanced_guide = skill.get_document_content("advanced-guide")
Available documents: SKILL, common-questions, advanced-guide, quickstart-by-task, objects, workflows, form-types-reference, readme
See readme.md for complete API documentation.
EdgarTools automatically handles SEC rate limiting (10 requests/second):
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 10,173 | 6,943 | -32% | 1 | 1 | 0% | 1,972 | 5,296 | +169% | 0 | 0 | — |
case-02 | fail→pass | 7,495 | 6,726 | -10% | 1 | 1 | 0% | 1,532 | 5,145 | +236% | 0 | 0 | — |
case-03 | fail→pass | 12,381 | 3,883 | -69% | 1 | 1 | 0% | 2,161 | 4,699 | +117% | 0 | 0 | — |
case-04 | pass→pass | 3,605 | 2,327 | -35% | 1 | 1 | 0% | 589 | 4,330 | +635% | 0 | 0 | — |
case-05 | fail→pass | 7,666 | 2,254 | -71% | 1 | 1 | 0% | 1,325 | 4,368 | +230% | 0 | 0 | — |
case-06 | fail→pass | 10,816 | 3,401 | -69% | 1 | 1 | 0% | 1,995 | 4,680 | +135% | 0 | 0 | — |
case-07 | fail→pass | 9,371 | 4,529 | -52% | 1 | 1 | 0% | 1,839 | 4,911 | +167% | 0 | 0 | — |
case-08 | fail→pass | 13,346 | 3,099 | -77% | 1 | 1 | 0% | 2,511 | 4,517 | +80% | 0 | 0 | — |
case-09 | fail→pass | 8,616 | 2,529 | -71% | 1 | 1 | 0% | 1,476 | 4,390 | +197% | 0 | 0 | — |
case-10 | pass→pass | 7,325 | 3,569 | -51% | 1 | 1 | 0% | 1,329 | 4,614 | +247% | 0 | 0 | — |
case-11 | pass→pass | 8,148 | 4,067 | -50% | 1 | 1 | 0% | 1,554 | 4,764 | +207% | 0 | 0 | — |
case-12 | fail→pass | 13,178 | 4,201 | -68% | 1 | 1 | 0% | 2,646 | 4,743 | +79% | 0 | 0 | — |
case-17 | fail→pass | 9,738 | 2,564 | -74% | 1 | 1 | 0% | 1,625 | 4,417 | +172% | 0 | 0 | — |
case-13 | fail→pass | 10,067 | 3,423 | -66% | 1 | 1 | 0% | 1,849 | 4,566 | +147% | 0 | 0 | — |
case-14 | pass→pass | 6,613 | 4,584 | -31% | 1 | 1 | 0% | 1,235 | 4,772 | +286% | 0 | 0 | — |
case-15 | pass→pass | 3,690 | 2,269 | -39% | 1 | 1 | 0% | 569 | 4,372 | +668% | 0 | 0 | — |
case-16 | fail→pass | 15,882 | 3,950 | -75% | 1 | 1 | 0% | 2,642 | 4,726 | +79% | 0 | 0 | — |
case-18 | pass→pass | 9,432 | 5,015 | -47% | 1 | 1 | 0% | 1,763 | 4,839 | +174% | 0 | 0 | — |
case-19 | fail→fail | 10,425 | 7,609 | -27% | 1 | 1 | 0% | 1,952 | 5,407 | +177% | 0 | 0 | — |
case-20 | pass→pass | 15,332 | 11,409 | -26% | 1 | 1 | 0% | 2,968 | 6,161 | +108% | 0 | 0 | — |
case-21 | pass→pass | 7,538 | 4,661 | -38% | 1 | 1 | 0% | 1,586 | 4,905 | +209% | 0 | 0 | — |
case-22 | pass→pass | 13,199 | 9,346 | -29% | 1 | 1 | 0% | 2,479 | 5,649 | +128% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +55 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.