Metadata-Version: 2.5
Name: quanticdata
Version: 0.2.0
Summary: Official Python SDK for the QuanticData API — web scraping to Markdown, SERP search, crawl/map, 74 ready-made Collectors and residential/mobile/datacenter proxy generation.
Project-URL: Homepage, https://quanticdata.io
Project-URL: Documentation, https://quanticdata.io/docs
Project-URL: Repository, https://github.com/quanticdata/quanticdata-python
Author-email: QuanticData <support@quanticdata.io>
License: MIT
License-File: LICENSE
Keywords: ai-agents,crawler,data-extraction,google-search,proxy,quanticdata,residential-proxies,scraper,serp,web-scraping
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: requests>=2.25
Description-Content-Type: text/markdown

# quanticdata — Python SDK for the QuanticData API

Scrape any page to clean Markdown, run structured Google/Bing/DuckDuckGo
searches, crawl and map whole sites, run 74 ready-made Collectors
(Amazon, Google Maps, LinkedIn jobs, app stores…), build datasets from a
plain-language prompt — everything through QuanticData' residential
proxy network with real-browser TLS fingerprints. Pay per successful call;
blocked pages cost nothing.

```bash
pip install quanticdata
```

## Quickstart

```python
from quanticdata import QuanticData

client = QuanticData()  # reads QUANTICDATA_API_KEY from the environment

page = client.scrape("https://example.com")
print(page["title"], page["engine"])
print(page["content"])          # the page as clean Markdown
```

Get a free API key at [quanticdata.io](https://quanticdata.io) — every
account includes free monthly usage, no card required. Set it once:

```bash
export QUANTICDATA_API_KEY=qd_live_your_key_here
```

## What's in the box

Every REST endpoint, one method each — responses come back with the API
envelope already unwrapped:

```python
# Structured search — 3 engines, 17 verticals, SerpApi-compatible JSON
serp = client.search("best espresso machine", country="us", num=20)
for r in serp["organic"]:
    print(r["rank"], r["title"], r["link"])

# SERP → citation-ready Markdown context for an AI prompt
ctx = client.search_and_read("latest EU AI act status", top_n=3)

# Map a site's URLs in seconds (sitemaps + homepage links)
urls = client.map("https://stripe.com", search="/blog")

# Async crawl — wait=True polls until it settles and returns the pages
job = client.crawl("https://docs.python.org", limit=30, depth=2, wait=True)

# Batch-scrape known URLs
job = client.batch(["https://a.example", "https://b.example"], wait=True)

# CSS/AI extraction on one page
data = client.scrape(
    "https://books.toscrape.com",
    extract={"titles": {"selector": "h3 a", "attr": "title", "all": True}},
)

# Learn selectors once with an LLM, then scrape the same layout for free
parser = client.generate_parser(
    "https://news.ycombinator.com",
    fields={"titles": "every story title, as a list"},
)

# 74 ready-made Collectors — semantic input instead of URLs
places = client.run_collector(
    "google_maps_places", keyword="dentist", location="Austin, TX", max_results=20
)

# Dataset from a prompt (validated rows, budget-capped)
ds = client.create_dataset(
    "coffee roasters in Portland with email and phone",
    limits={"max_rows": 50, "max_cost_usd": 2},
    wait=True,
)

# Proxy endpoints of every type — residential, mobile, datacenter, ISP, IPv6
plans = client.list_proxies(active=True)
proxies = client.generate_proxies(plans["proxies"][0]["orderId"], country="us", quantity=5)
```

## Web Unlocker

`unlock()` replays any HTTP request — method, headers, body — through a
residential exit with a real browser TLS fingerprint, retries on a fresh IP
when the target blocks it, and escalates a blocked GET to a real browser.
You get the raw response back: `status`, `headers`, `body`, `finalUrl`.

```python
r = client.unlock("https://www.example-shop.com/item/42", country="us")
if r["blocked"]:
    print(r["blockClass"], r.get("vendor"), r.get("blockReason"))  # e.g. "waf", "cloudflare"
else:
    print(r["status"], r["body"][:200])

# Force a real browser render and wait for the price to appear
page = client.unlock(
    "https://www.example-shop.com/item/42",
    render="html", wait_for_selector=".price", wait_ms=1500,
)
```

A still-blocked page is never returned as a silent 200: it comes flagged
with `blocked: true` (pass `fail_on_block=True` to get an error instead).
Interactive captchas are not solved — they arrive with `blockClass: "captcha"`.
Billed per GB of the tier's prepaid unlocker balance (`usage` in the response).

## Errors and retries

Failures raise `QuanticDataError` with `.status`, `.message` and
`.payload`. Connection errors and HTTP 429 are retried with backoff;
billable calls are never re-sent after a response was received, so nothing
gets double-billed behind your back.

```python
from quanticdata import QuanticData, QuanticDataError

try:
    QuanticData(api_key="qd_live_wrong").scrape("https://example.com")
except QuanticDataError as err:
    print(err.status, err.message)
```

## Also available

- **MCP server** for Claude, Cursor and any MCP client:
  [`npx -y quanticdata-mcp`](https://www.npmjs.com/package/quanticdata-mcp)
  exposes the same 25 tools to AI agents.
- **REST reference**: [quanticdata.io/docs](https://quanticdata.io/docs)

MIT licensed.
