tickertape-client
An unofficial, asynchronous, typed Python SDK and client for TickerTape featuring persistent caching, Next.js hydration payload extraction, and a high-performance SQLite-backed ISIN lookup engine.
Features
- Asynchronous & Fast: Built on top of
httpxandasynciofor non-blocking HTTP requests and concurrent scraping. - Sitemap Discovery & Caching: Automatic fetching, XML parsing (
<urlset>and<sitemapindex>), and local JSON disk caching of TickerTape sitemaps. - Deep Mutual Fund Extraction: Parses Next.js SSR hydration payloads (
__NEXT_DATA__) into typed Pydantic models with NAV, expense ratios, AUM, scorecard metrics, and AMC details. - ISIN Resolution & Lookup Engine:
- Fast, indexed SQLite database mapping mutual fund ISINs (e.g.
INF966L01721) to TickerTape records. - Targeted on-demand fuzzy resolver with candidate scoring and live verification.
- Query peer mutual funds and cluster schemes by sector, subsector, plan (
Direct/Regular), option (Growth/IDCW), and benchmark.
- Fast, indexed SQLite database mapping mutual fund ISINs (e.g.
- Resumable Bulk Indexer: Crawl thousands of sitemap URLs with configurable concurrency, rate limiting, and progress tracking callbacks.
- Extensible Architecture: Modular parser registry pattern (
BaseParser,register_parser) with stubs for future asset types (stocks, ETFs, screens). - Fully Typed: Strict type hints and Pydantic v2 validation models.
Installation
pip install tickertape-client
Or using uv:
uv add tickertape-client
Quickstart
import asyncio
from tickertape import TickerTapeClient
async def main():
async with TickerTapeClient() as client:
# 1. Fetch parsed sitemap URLs (cached locally on disk after first call)
sitemap_items = await client.sitemap.get("mf")
print(f"Found {len(sitemap_items)} mutual fund URLs in sitemap")
# 2. Fetch mutual fund details by slug or MFID
fund = await client.mf.get("quant-infrastructure-fund-M_QUNG")
print(f"Fund: {fund.name}")
print(f"ISIN: {fund.isin} | NAV: INR {fund.nav}")
if fund.meta:
print(f"Benchmark: {fund.meta.benchmark_index}")
print(f"Expense Ratio: {fund.meta.expense_ratio}%")
print(f"AUM: INR {fund.meta.aum} Cr")
# 3. Resolve and fetch fund details directly by ISIN
fund_by_isin = await client.mf.get_by_isin(
isin="INF966L01721",
hint_name="Quant Infrastructure Fund",
)
if fund_by_isin:
print(f"Resolved from ISIN: {fund_by_isin.name}")
# 4. Find peer funds in the same category
peers = client.mf.get_peers("INF966L01721", limit=5)
for peer in peers:
print(f"Peer: {peer.name} ({peer.isin})")
if __name__ == "__main__":
asyncio.run(main())
Runnable Example Scripts
The examples/ directory contains ready-to-run demonstration scripts for every feature:
| Example Script | Description |
|---|---|
examples/all_features_demo.py |
Complete Tour: Runs through every single feature and function in one script. |
examples/01_basic_usage.py |
Client options, sitemap caching, fund extraction, raw props, error handling. |
examples/02_isin_lookup_and_peers.py |
Targeted ISIN resolution, SQLite CRUD/batch ops, peer clustering, filtering. |
examples/03_bulk_indexing_and_export.py |
Resumable bulk indexer with progress callback, exporting to JSON & CSV. |
examples/04_custom_parser.py |
Subclassing BaseParser, registry extension, custom data model extraction. |
Run any example directly with uv:
uv run python examples/all_features_demo.py
Detailed Feature Reference
1. TickerTapeClient Lifecycle & Configuration
from pathlib import Path
from tickertape import TickerTapeClient
# Custom configuration options
client = TickerTapeClient(
base_url="https://www.tickertape.in",
timeout=30.0,
cache_dir=Path(".cache/tickertape"),
headers={"User-Agent": "MyCustomBot/1.0"},
)
# Async context manager ensures graceful connection cleanup
async with client:
# Direct raw request helper if needed:
html = await client.request("GET", "/mutualfunds/quant-infrastructure-fund-M_QUNG")
2. Sitemaps (client.sitemap)
Manage TickerTape's XML sitemaps with local JSON caching:
# Load mutual fund sitemap (uses local cache if present, otherwise fetches live XML)
items = await client.sitemap.get("mf")
# Bypass cache and force a live download + update local cache
refreshed = await client.sitemap.refresh("mf")
# Inspect parsed sitemap records
for item in items[:5]:
print(item.record_id, item.url, item.last_modified, item.priority)
# Parse a sitemap index (<sitemapindex>) containing child sitemaps
references = await client.sitemap.get_references("https://example.com/sitemap_index.xml")
# Check cache status & clear cache
is_cached = client.sitemap.is_cached("mf")
client.sitemap.clear_cache("mf") # or client.sitemap.clear_cache() for all
Supported default sitemap categories: "mf", "stocks", "etf", "us-stocks", "us-etf".
3. Mutual Funds (client.mf)
Extract structured data from HTML and embedded __NEXT_DATA__ JSON hydration payloads:
# Fetch complete mutual fund detail
fund = await client.mf.get("quant-infrastructure-fund-M_QUNG")
# Core identifiers & NAV
print(fund.mf_id, fund.name, fund.isin, fund.nav)
# Security-level info
if fund.security_info:
print(fund.security_info.amc, fund.security_info.nav_ch_1d, fund.security_info.option)
# Granular fund metadata
if fund.meta:
print(fund.meta.benchmark_index, fund.meta.expense_ratio, fund.meta.aum)
# Scorecard items (Performance, Risk, Cost, etc.)
for item in fund.scorecard:
print(item.name, item.tag, item.colour)
# Convenience helper to fetch just the ISIN
isin = await client.mf.get_isin("quant-infrastructure-fund-M_QUNG")
# Raw Next.js pageProps dictionary
raw_props = await client.mf.get_raw("quant-infrastructure-fund-M_QUNG")
4. ISIN Targeted Resolution
Resolve an ISIN directly using the SQLite lookup table or on-demand fuzzy sitemap slug matching:
# Resolves ISIN via SQLite table first; if not indexed yet, uses hint_name to match
# candidate URLs in the sitemap, fetches the page, verifies ISIN, and saves to SQLite.
fund = await client.mf.get_by_isin(
isin="INF966L01721",
hint_name="Quant Infrastructure Fund - Growth - Direct Plan",
)
5. Persistent SQLite Lookup Table (client.mf.lookup)
Fast local database (.cache/tickertape/isin_lookup.db) with auto-migration and indexing:
table = client.mf.lookup
# Query single record by ISIN (case-insensitive)
mapping = table.get("INF966L01721")
# Query by TickerTape record_id
mapping = table.get_by_record_id("M_QUNG")
# Batch query multiple ISINs
results = await client.mf.get_cached_by_isin_batch(["INF966L01721", "INF209K01157"])
# Upsert single or batch records
table.upsert(mapping)
table.upsert_batch([mapping1, mapping2])
# Export database to JSON or CSV
table.export_json("exports/funds.json")
table.export_csv("exports/funds.csv")
# Clear table
table.clear()
6. Peer & Category Clustering
Cluster funds and find comparable peers using classification tags:
# Find peers matching same subsector, plan (Direct/Regular), and option (Growth/IDCW)
peers = client.mf.get_peers("INF966L01721", match_plan=True, match_option=True, limit=10)
# Filter indexed funds by classification attributes
large_caps = client.mf.find_funds(subsector="Large Cap Fund", plan="Direct", option="Growth")
nifty_funds = client.mf.find_funds(benchmark="Nifty 50 - TRI")
hdfc_funds = client.mf.find_funds(amc="HDFC")
7. Resumable Bulk Indexing
Asynchronously crawl and index mutual funds in bulk:
def progress(completed, total, successful, failed):
print(f"\rIndexed {completed}/{total} | Success: {successful} | Failed: {failed}", end="")
# Resumable crawl: skips record_ids already present in SQLite database
indexed = await client.mf.build_isin_index(
concurrency=5, # Concurrent workers
delay=0.5, # Throttle delay (seconds) per worker
limit=100, # Optional batch limit
progress_callback=progress,
force_refresh=False,
)
# Force re-download of sitemap XML and re-index all funds:
indexed = await client.mf.build_isin_index(force_refresh=True)
8. Custom Parser Extension
Extend the client pipeline with custom parsers for new content types:
from tickertape.parsers import BaseParser, get_parser, register_parser
class CustomStockParser(BaseParser[dict]):
def parse(self, content):
# Extract custom fields from HTML or JSON
return {"custom_parsed": True}
# Register by name
register_parser("custom_stock", CustomStockParser)
# Instantiate anywhere
parser = get_parser("custom_stock")
result = parser.parse({"raw": "data"})
9. Error Handling
Focused and practical exception hierarchy:
from tickertape.errors import (
TickerTapeError, # Base exception
TickerTapeHTTPError, # HTTP 4xx/5xx or network failures
TickerTapeNotFoundError, # Specific HTTP 404 (subclass of HTTPError)
TickerTapeParseError, # Failed to parse XML, HTML, or Next.js JSON
)
try:
fund = await client.mf.get("unknown-slug")
except TickerTapeNotFoundError as exc:
print(f"404 Not Found: {exc.status_code}")
except TickerTapeParseError as exc:
print(f"Parsing failed: {exc}")
except TickerTapeHTTPError as exc:
print(f"HTTP error: {exc.status_code}")
Data Models
All models are built with Pydantic v2 and allow ignoring unrecognized extra attributes:
MutualFundDetail: Complete mutual fund entity (mf_id,name,isin,slug,nav,security_info,meta,scorecard,raw_props).MFSecurityInfo: Core security fields (mf_id,name,amc,nav_close,sector,subsector, etc.).MFMeta: In-depth fund metadata (benchmark_index,fund_type,risk_classification,expense_ratio,aum, etc.).MFScorecardItem: Scorecard metrics (name,tag,colour,description).ISINMapping: SQLite-persisted ISIN record with classification attributes for peer clustering.SitemapURL: Parsed<url>sitemap record (record_id,url,last_modified,change_frequency,priority).
Development & Testing
Clone the repository and install dependencies with uv:
git clone https://github.com/folioman/tickertape-client.git
cd tickertape-client
uv sync
Run test suite:
uv run pytest
Build distributions:
uv build
Verify distribution metadata:
uvx twine check dist/*
Publishing to PyPI
Automated Releases via GitHub Actions
This repository is configured with GitHub Actions to publish automatically when a GitHub Release is published, or manually via Actions > Publish to PyPI. See PyPI Publishing Guide for details on setting up PyPI Trusted Publishing (OIDC).
Manual Publishing via CLI
# Upload to TestPyPI
uv publish --publish-url https://test.pypi.org/legacy/ --token <TEST_PYPI_TOKEN>
# Upload to Production PyPI
uv publish --token <PYPI_TOKEN>
License
This project is licensed under the Apache License 2.0.
Disclaimer
This software is an unofficial, community-driven client library. It is neither created, maintained, endorsed, nor supported by TickerTape or its affiliates. Use this tool responsibly, in compliance with all applicable terms of service and rate limits.
Release files for tickertape-client 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tickertape_client-0.1.0.tar.gz | 242.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tickertape_client-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 277.5 kB
Release files / tickertape_client-0.1.0.tar.gz
| Download URL | tickertape_client-0.1.0.tar.gz |
|---|---|
| Size | 242.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
37cda2254fee9f407f9d31099d545ebc199fe37de4d0cde988ef13e42ceb1b58
|
|
BLAKE2b-256 checksum How to use checksums |
3c934c53646a31bd54769fe3a5821e1a265b2ad9b4adce30ed1338566bd0453f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency logRelease files / tickertape_client-0.1.0-py3-none-any.whl
| Download URL | tickertape_client-0.1.0-py3-none-any.whl |
|---|---|
| Size | 35.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b4f372473baffaf792b6bb221c78d853fe39d982dfc1a9f63201bf014664ca6d
|
|
BLAKE2b-256 checksum How to use checksums |
e67fde41e681a343b1303fe9d33326846b6a72d1c7af20a28458794c9cea4c8d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency log