# EdgarKit
<div align="center">
<img src=".assets/mascot.png" alt="EdgarKit Mascot" width="200">
</div>
[](https://crates.io/crates/edgarkit)
[](https://docs.rs/edgarkit)
[](https://opensource.org/licenses/MIT)
An unofficial Rust client for the SEC EDGAR (Electronic Data Gathering, Analysis, and Retrieval) system.
## Why EdgarKit
EdgarKit is built for financial apps and high-throughput, production-grade pipelines that need to ingest, search, and process SEC filings reliably and fast. It’s a great fit for:
- High-performance financial data pipelines (ETL and streaming)
- Quantitative and fundamental investment research
- Corporate event tracking and governance analytics
- Compliance monitoring and audit workflows
- Building dashboards and alerting for market-moving filings
Rust shines here: many SEC filings (especially S-1, 10-K, 10-Q) are large and complex. Parsing, validating, and extracting structure from these can be very CPU- and IO-intensive. With Rust’s zero-cost abstractions and async runtime, you can scale to millions of documents with predictable latency and minimal overhead.
Compared to Python tools like `edgartools` or `sec-edgar-downloader`, Rust typically:
- Processes heavy filings dramatically faster (no GIL, native threading)
- Uses far less memory (no large dynamic overhead)
- Offers compile-time guarantees and stronger type safety
- Integrates cleanly into modern distributed systems (containers, services)
If you’ve hit bottlenecks with scripting solutions, EdgarKit lets you keep the developer ergonomics while upgrading performance and reliability.
## Features
- **🚦 Rate-Limited HTTP Client** - Automatic compliance with SEC.gov fair access rules
- **📄 Filing Operations** - Access company filings, submissions, and documents
- **🏢 Company Information** - Retrieve company facts, tickers, and metadata
- **🔍 Search Capabilities** - Find filings with customizable search criteria
- **📡 Feed Operations** - Monitor Atom and RSS feeds for filings and news
- **📊 Index Operations** - Download and parse daily and quarterly filing indices
- **⚡ Async-First** - Built on tokio for high-performance concurrent operations
- **🎯 Type-Safe** - Strongly-typed API with comprehensive error handling
- **🔧 Flexible** - Feature flags for modular compilation
## Installation
Add EdgarKit to your `Cargo.toml`:
```toml
[dependencies]
edgarkit = "0.1.0"
tokio = { version = "1", features = ["full"] }
```
### Feature Flags
EdgarKit uses feature flags to allow you to compile only what you need:
```toml
[dependencies]
edgarkit = { version = "0.1.0", features = ["search", "filings", "company"] }
```
Available features:
- `search` - Search API functionality (requires `serde_urlencoded`, `futures`)
- `filings` - Filing operations (requires `flate2`, `chrono`)
- `company` - Company information APIs (requires `chrono`)
- `feeds` - RSS/Atom feed support (requires `quick-xml`)
- `index` - Index file operations (requires `flate2`, `chrono`, `regex`)
Default features: `["search", "filings", "company", "feeds", "index"]` (all features enabled)
## Quick Start
```rust
use edgarkit::{Edgar, FilingOperations, FilingOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize the client with a proper user agent
// SEC.gov requires format: "AppName contact@example.com"
let edgar = Edgar::new("MyApp contact@example.com")?;
// Get recent 10-K filings for Apple (CIK: 320193)
let options = FilingOptions::new()
.with_form_type("10-K")
.with_limit(5);
let filings = edgar.filings("320193", Some(options)).await?;
for filing in filings {
println!("Filed: {} - {}", filing.filing_date, filing.form);
}
Ok(())
}
```
## Filing Types You’ll Use Most
Understanding common forms helps target the right data:
- 8-K: Current reports for material events. Ideal for event tracking (mergers, leadership changes, financing, bankruptcy). See the official guide: https://www.sec.gov/files/form8-k.pdf
- 10-K: Annual report with audited financials, risk factors, MD&A, business overview. Deep, comprehensive view. https://www.sec.gov/files/form10-k.pdf
- 10-Q: Quarterly report with unaudited financials and updates. More frequent pulse than 10-K. https://www.sec.gov/files/form10-q.pdf
Other frequent forms for governance and ownership:
- 3/4/5: Insider ownership changes
- Schedule 13D/13G: Beneficial ownership disclosures
- Form D: Exempt offerings
- Investment company forms like `NCEN`, `N-PORT`, `N-CSR`
## Tips & Tricks
- `DetailedFiling.items`: Quickly scan 8-K items to identify important events. The official 8-K item reference is here: https://www.sec.gov/files/form8-k.pdf. For example, items like `1.01, 2.03, 5.01` indicate significant agreements, creation of liabilities, or a change in control of registrant (5.01).
- `is_xbrl` vs `is_inline_xbrl`: Indicates whether the filing contains XBRL (machine-readable financials) or Inline XBRL (embedded in HTML). Use XBRL parsers for precise numeric extraction; Inline XBRL often improves context and presentation.
- `primary_document`: Often the main HTML/XML file to parse. If you fetch the text filing, the primary document usually appears first.
- Use feature filters and `FilingOptions` to constrain the workload (form types, limits, offsets). For S-1 workflows, consider including amendments (S-1/A) or disabling them when you need only originals.
## Companion Crates (Recommended)
- `crabrl`: High-performance XBRL parser and validator for financial statements. Parse us-gaap concepts at scale. https://crates.io/crates/crabrl
- `quick-xml`: Fast XML parsing, perfect for lightweight forms (3/4/5, Form D, NCEN, Schedule 13D/13G) and structured feeds. https://crates.io/crates/quick-xml
- `rig.rs`: For complex, narrative-heavy filings (S-1, 10-K, 10-Q), use rig.rs with strong models (DeepSeek 3.2, Claude Haiku 4.5, Qwen Plus) to extract sections, summarize, and classify. https://rig.rs/
## Why Rust (A Short Story)
I originally built a filing pipeline in TypeScript. It worked—until it needed to process heavy S-1 filings at scale. Regex-based parsing slowed to a crawl, memory usage spiked, and throughput collapsed. Rewriting the pipeline in Rust solved the core problems: faster IO, deterministic performance, safe concurrency, and efficient parsing. EdgarKit is the distilled client layer born from that migration.
## Usage Examples
Examples are provided in the `examples/` directory to keep this README concise.
### Download Filing Content
```rust
use edgarkit::{Edgar, FilingOperations};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let edgar = Edgar::new("MyApp contact@example.com")?;
// Get the latest 10-K for a company
let content = edgar.get_latest_filing_content("320193", &["10-K"]).await?;
// Save to file or process the content
println!("Downloaded {} bytes", content.len());
Ok(())
}
```
### Access Index Files
```rust
use edgarkit::{Edgar, EdgarDay, IndexOperations, FilingOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let edgar = Edgar::new("MyApp contact@example.com")?;
// Get all filings from a specific day
let day = EdgarDay::new(2024, 8, 15)?;
let options = FilingOptions::new().with_form_type("10-K");
let filings = edgar.get_daily_filings(day, Some(options)).await?;
for filing in filings {
println!("{} - {}", filing.company_name, filing.form_type);
}
Ok(())
}
```
## More Examples
Check out the `examples/` directory for comprehensive examples:
- [`basic_usage.rs`](examples/basic_usage.rs) - Getting started with EdgarKit
- [`search_filings.rs`](examples/search_filings.rs) - Advanced search patterns
- [`download_filings.rs`](examples/download_filings.rs) - Filing retrieval and processing
- [`rss_feeds.rs`](examples/rss_feeds.rs) - Working with RSS/Atom feeds
- [`index_operations.rs`](examples/index_operations.rs) - Index file operations
Run any example with:
```bash
cargo run --example basic_usage --all-features
```
## Mini-Projects
EdgarKit includes two standalone CLI tools in the `examples/` directory that demonstrate real-world usage:
### IPO Scanner
Scans recent EDGAR daily indices for S-1 filings (IPOs) and displays them in an interactive terminal UI (TUI).
```bash
# Run from examples/ipo-scanner
cargo run --release -- --weekly
```
### Investment Adviser
A CLI that fetches the latest 10-K/10-Q filings and uses an LLM (via OpenRouter) to generate investment recommendations.
```bash
# Run from examples/investment-adviser
export OPENROUTER_API_KEY="..."
cargo run --release -- --ticker AAPL --model deepseek/deepseek-v3.2
```
## Rate Limiting
EdgarKit automatically handles rate limiting to comply with SEC.gov's fair access policy:
- **Default**: 10 requests per second
- **Configurable**: Adjust via `EdgarConfig`
- **Automatic retry**: Exponential backoff on rate limit errors
```rust
use edgarkit::{Edgar, EdgarConfig, EdgarUrls};
use std::time::Duration;
let config = EdgarConfig {
user_agent: "MyApp contact@example.com".to_string(),
rate_limit: 5, // 5 requests per second
timeout: Duration::from_secs(30),
base_urls: EdgarUrls::default(),
};
let edgar = Edgar::with_config(config)?;
```
## SEC.gov Compliance
When using EdgarKit, please follow SEC.gov's guidelines:
1. **User Agent Required**: Always provide a descriptive user agent with contact information
2. **Rate Limiting**: Respect the 10 requests/second limit (enforced automatically)
3. **Fair Use**: Avoid excessive bulk downloading during peak hours (9 AM - 5 PM ET)
4. **Terms of Service**: Review [SEC.gov's guidelines](https://www.sec.gov/os/accessing-edgar-data)
## Error Handling
EdgarKit provides comprehensive error types:
```rust
use edgarkit::{Edgar, EdgarError, FilingOperations};
match edgar.filings("invalid-cik", None).await {
Ok(filings) => println!("Found {} filings", filings.len()),
Err(EdgarError::NotFound) => println!("Company not found"),
Err(EdgarError::RateLimitExceeded) => println!("Rate limit hit"),
Err(e) => println!("Error: {}", e),
}
```
## Documentation
Full API documentation is available at [docs.rs/edgarkit](https://docs.rs/edgarkit).
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
### Development Setup
```bash
git clone https://github.com/r007/edgarkit.git
cd edgarkit
cargo build --all-features
cargo test --all-features
```
### Running Tests
```bash
# Run unit tests
cargo test --lib
# Run all tests including integration tests
cargo test --all-features
# Run integration tests separately (requires network)
cargo test --all-features -- --ignored
```
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Acknowledgments
- Inspired in part by Joey Chilson’s work-in-progress [`edgar_client`](https://github.com/joeychilson/edgar_client) (Elixir/Rust). Thanks to Joey for publishing the endpoint URLs and early implementation ideas that helped shape this client; EdgarKit rewrites and extends those concepts in a Rust-first, consistent API.
- Built with [reqwest](https://github.com/seanmonstar/reqwest) for HTTP requests
- Rate limiting via [governor](https://github.com/benwis/governor)
- XML parsing with [quick-xml](https://github.com/tafia/quick-xml)
- Powered by the [tokio](https://tokio.rs/) async runtime
## Author
Created by [Sergey Monin](https://github.com/r007)
## Disclaimer
This library is not affiliated with or endorsed by the U.S. Securities and Exchange Commission. Please ensure your use complies with SEC.gov's terms of service and applicable regulations.
---
Made with ❤️ for the Rust community