Skip to main content

Async screener.in scraper with MCP server and CLI for NSE/BSE stock data

Project description

screener-ai-tool

An async Python toolkit for fetching and analyzing Indian (NSE/BSE) stock data from screener.in — fundamentals, price history, technical indicators, peer comparisons, shareholding patterns, and corporate documents/announcements. Ships as a CLI (screener), a library (screener_ai), and an MCP server for use with Claude and other LLM clients.

Disclaimer: This is a personal-use tool for analyzing publicly visible data on screener.in. It is not affiliated with or endorsed by screener.in. Be polite: respect screener.in's Terms of Service, keep request rates low (defaults are conservative), prefer an authenticated session for heavier usage, and do not use this tool to circumvent rate limits or scrape at scale. You are responsible for how you use this tool.

Architecture

                         ┌───────────────────────────┐
                         │        screener.in         │
                         │  (HTML pages + JSON APIs)   │
                         └──────────────┬─────────────┘
                                         │ httpx (rate-limited, retried)
                                         ▼
                         ┌───────────────────────────┐
                         │       client.py            │
                         │  ScreenerClient             │
                         │  - RateLimiter (token bkt)  │
                         │  - retries + backoff        │
                         │  - cookie jar / session      │
                         └──────────────┬─────────────┘
                                         │
                ┌────────────────────────┼─────────────────────────┐
                ▼                        ▼                          ▼
        ┌──────────────┐        ┌───────────────┐          ┌──────────────┐
        │  parsers.py   │        │  auth.py       │          │ indicators.py │
        │  HTML/JSON →  │        │  login/session │          │ SMA/EMA/RSI/  │
        │  pydantic     │        │  persistence   │          │ MACD/Bollinger│
        │  models       │        │                │          │ /Stochastic   │
        └──────┬────────┘        └───────┬────────┘          └──────┬────────┘
                │                          │                          │
                └────────────┬─────────────┴────────────┬────────────┘
                              ▼                          ▼
                      ┌───────────────────────────────────────┐
                      │             service.py                  │
                      │           ScreenerService                │
                      │  high-level facade (search, overview,   │
                      │  price_history, financials, peers,      │
                      │  shareholding, documents, technical,     │
                      │  snapshot) — page-cache(8) per instance  │
                      └───────┬───────────────────┬─────────────┘
                               │                   │
                ┌──────────────▼───┐     ┌─────────▼──────────┐
                │     bulk.py        │     │     export.py       │
                │  bulk_fetch over   │     │  JSON/CSV/Parquet    │
                │  many symbols      │     │  export              │
                │  (semaphore-bound) │     │                      │
                └──────────────┬─────┘     └─────────┬───────────┘
                               │                       │
                ┌──────────────▼───────────────────────▼───────────┐
                │                  Interfaces                        │
                │  ┌────────────────────┐   ┌──────────────────────┐│
                │  │     cli.py          │   │   mcp_server.py       ││
                │  │  `screener ...`     │   │  FastMCP server        ││
                │  │  typer + rich       │   │  `screener_*` tools     ││
                │  └────────────────────┘   └──────────────────────┘│
                └─────────────────────────────────────────────────────┘

Installation

Have your agent install it (recommended)

This repo ships an llms.txt written for AI coding agents. Paste this into your agent (Claude Code, Cursor, Codex, etc.):

Fetch and follow the instructions at
https://raw.githubusercontent.com/singhvedant/screener-ai-tool/main/llms.txt
to install screener-ai-tool, register its MCP server, and install its skill.

The agent will: install the package (pip/uv), register the screener MCP server, copy skills/screener-ai-tool/SKILL.md into its own skills directory (so the skill can be toggled on/off independently later), and verify everything works end-to-end.

Manual installation

Requires Python 3.11+.

pip install screener-ai-tool
# or
uv pip install screener-ai-tool

Or from source, with uv:

git clone https://github.com/singhvedant/screener-ai-tool.git
cd screener-ai-tool

# create a virtual environment and install in editable mode with dev deps
uv venv
source .venv/bin/activate
uv pip install -e ".[dev]"

After installation the screener CLI entry point is available (or run via uv run screener ... / python -m screener_ai ...).

Authentication & session persistence

screener.in allows limited anonymous browsing (~50 page views/day) before showing rate-limit prompts. Logging in with your screener.in account raises those limits significantly.

# interactive (prompts for password, hidden input)
screener login --email you@example.com

# or via environment variables (useful for CI / scripts)
export SCREENER_EMAIL=you@example.com
export SCREENER_PASSWORD=your-password
screener login

# check status
screener auth-status

# log out (clears saved session)
screener logout

On success, the session cookie (sessionid) is written to ~/.screener-ai/session.json (mode 0600, JSON of cookie name → value). All subsequent CLI/MCP/library calls reuse this session automatically until it expires or screener logout is run. Credentials and cookies are never logged.

CLI usage

All commands support --json for raw JSON output (useful for piping into jq or other tools), and most accept --days / --consolidated/--standalone where relevant. Async commands wrap asyncio.run; errors print a message to stderr and exit with code 1 (authentication errors suggest screener login).

screener search QUERY

Search for companies by name or symbol.

screener search reliance
screener search tata --json

screener price SYMBOL [--days 365] [--limit 30]

Show recent price history (rich table of the latest --limit rows).

screener price RELIANCE
screener price RELIANCE --days 90 --limit 10
screener price TCS --json > tcs_prices.json

screener overview SYMBOL

Company overview: name, sector/industry, key ratios, pros/cons.

screener overview RELIANCE
screener overview INFY --json

screener fundamentals SYMBOL [--statement profit-loss|quarters|balance-sheet|cash-flow|ratios]

Fetch a financial statement table.

screener fundamentals RELIANCE --statement quarters
screener fundamentals RELIANCE --statement balance-sheet --json

screener technical SYMBOL [--days 365] [--series]

Technical analysis snapshot (SMA/EMA/RSI/MACD/Bollinger + signals). Pass --series to include full indicator time series.

screener technical RELIANCE
screener technical RELIANCE --days 180 --series --json

screener events SYMBOL / screener news SYMBOL

events shows announcements + corporate documents; news is an alias view focused on announcements, credit ratings, and concall material.

screener events RELIANCE
screener news RELIANCE --json

screener peers SYMBOL

Peer comparison table (with median row).

screener peers RELIANCE

screener shareholding SYMBOL

Quarterly and yearly shareholding pattern tables.

screener shareholding RELIANCE

screener snapshot SYMBOL

Aggregated "everything we know" snapshot — overview, financial tables, shareholding, peers, documents, and technical analysis, fetched concurrently.

screener snapshot RELIANCE --json

screener bulk SYMBOLS... [--dataset price] [--concurrency 8] [--out FILE]

Fetch a dataset for many symbols concurrently. Per-symbol failures are captured (never raised) as {"error": "..."} entries.

screener bulk RELIANCE TCS INFY HDFCBANK --dataset overview
screener bulk RELIANCE TCS INFY --dataset price --days 90 --concurrency 16 --out prices.json

screener export SYMBOL [--what price|fundamentals|snapshot] [--fmt json|csv|parquet] [--out FILE]

Export data to JSON, CSV, or Parquet (CSV/Parquet for tabular data such as price history and financial tables via pandas).

screener export RELIANCE --what price --fmt csv --out reliance_price.csv
screener export RELIANCE --what snapshot --fmt json --out reliance_snapshot.json

screener serve [--transport stdio|http] [--host 127.0.0.1] [--port 8631]

Run the MCP server (see below).

MCP setup

stdio transport (recommended for Claude Code / Claude Desktop)

# if installed via pip/uv (entry point on PATH)
claude mcp add screener -- screener serve

# if running from a cloned repo
claude mcp add screener -- uv run --directory ~/Development/screener-ai-tool screener serve

This registers a screener MCP server that Claude launches on demand via stdio.

HTTP transport

To run the server over streamable HTTP (e.g. for remote access or shared deployments):

uv run --directory ~/Development/screener-ai-tool screener serve --transport http --host 127.0.0.1 --port 8631

Then point an MCP-compatible client at http://127.0.0.1:8631.

MCP tool list

All tools return JSON-serializable dicts (model_dump).

Tool Description
screener_login(email, password) Authenticate and persist a session (use when rate-limited as anonymous)
screener_auth_status() Current authentication status
screener_search(query, limit=10) Search for companies
screener_price(symbol, days=365, limit=0) Price history (optionally truncated to last limit points)
screener_overview(symbol) Company overview + key ratios
screener_fundamentals(symbol, statement="profit-loss") Financial statement table
screener_technical(symbol, days=365, include_series=False) Technical indicators + signals
screener_peers(symbol) Peer comparison table
screener_shareholding(symbol) Shareholding pattern (quarterly/yearly)
screener_events(symbol) Announcements + corporate documents
screener_news(symbol) Announcements + credit ratings + concalls
screener_snapshot(symbol, days=365) Full aggregated snapshot
screener_bulk(symbols, dataset="price", days=365, concurrency=8) Bulk fetch over many symbols
screener_export(symbol, what="snapshot", fmt="json", out_path="") Export data to a file

Data models

Defined with pydantic v2 in screener_ai.models:

  • SearchResult — id, name, url, symbol (parsed from url)
  • CompanyRef — symbol, name, company_id, warehouse_id, consolidated
  • PricePoint / PriceHistory — date, close, dma50, dma200, volume, delivery_pct
  • KeyRatios — market_cap, current_price, high_52w, low_52w, pe, book_value, dividend_yield, roce, roe, face_value, extras
  • CompanyOverview — ref, about, website, bse_code, nse_code, sector, industry, ratios, pros, cons
  • FinancialTable — kind, columns, rows (raw strings) + .numeric() helper
  • ShareholdingPattern — quarterly / yearly FinancialTable
  • PeerRow / PeerComparison — peer metrics + median row
  • DocumentLink / CorporateDocs — announcements, annual reports, credit ratings, concalls
  • IndicatorSeries, MACDResult, BollingerResult — technical indicator series
  • TechnicalSnapshot / TechnicalAnalysis — latest indicator values + signals
  • FullSnapshot — everything aggregated for one symbol

Rate limiting & politeness

  • Default: 2 requests/second, burst of 5 (token-bucket RateLimiter).
  • On HTTP 429, the client backs off exponentially (with jitter) and honors Retry-After; if retries are exhausted, RateLimitError is raised.
  • Connection pooling is bounded (max_connections=20, keepalive=10).
  • Anonymous browsing is heavily throttled by screener.in (~50 page views/day). Log in (screener login) for a much higher effective limit, and consider lowering --concurrency for bulk/snapshot operations.
  • bulk_fetch / screener bulk isolate per-symbol errors — one bad symbol never aborts the whole batch.

Testing

# unit tests only (no network) — the default safe subset
pytest -m "not integration and not load"

# live integration tests (hits screener.in; skips gracefully on network errors)
pytest -m integration

# heavy load test (500+ symbols; requires network and takes a while)
pytest -m load

Unit tests use captured fixtures in tests/fixtures/ (real screener.in HTML and JSON responses) plus respx to mock httpx for client-level tests — no network access is required for pytest -m "not integration and not load".

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

screener_ai_tool-0.1.0.tar.gz (158.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

screener_ai_tool-0.1.0-py3-none-any.whl (41.1 kB view details)

Uploaded Python 3

File details

Details for the file screener_ai_tool-0.1.0.tar.gz.

File metadata

  • Download URL: screener_ai_tool-0.1.0.tar.gz
  • Upload date:
  • Size: 158.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for screener_ai_tool-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ee739cd3153608792a7c462c8cd107d1380864fba3c89dbab0403905078a86b7
MD5 bad149d02cd3627c5f1408aa9c8cb713
BLAKE2b-256 ed4439efd54f05eb8d5f44ea73d74a94b5bbe3d364ece227c3d54d849927cace

See more details on using hashes here.

Provenance

The following attestation bundles were made for screener_ai_tool-0.1.0.tar.gz:

Publisher: publish.yml on singhvedant/screener-ai-tool

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file screener_ai_tool-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for screener_ai_tool-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c3e53d59517cb1b3850bb3da0ea043a05a69c25bf6468023496255d07825e805
MD5 72253cf8be1ec3f27b13e36b9665b9e1
BLAKE2b-256 89409a779d2af3fe158206f29bc65a15c50535f034c269110585cdfd6ba6d562

See more details on using hashes here.

Provenance

The following attestation bundles were made for screener_ai_tool-0.1.0-py3-none-any.whl:

Publisher: publish.yml on singhvedant/screener-ai-tool

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page