alterlab 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,375 @@
1
+ Metadata-Version: 2.4
2
+ Name: alterlab
3
+ Version: 2.0.0
4
+ Summary: Official Python SDK for the AlterLab Web Scraping API - Extract data from any website with intelligent anti-bot bypass
5
+ License: MIT
6
+ Keywords: web-scraping,scraping,api,data-extraction,anti-bot,javascript-rendering,headless-browser,proxy,alterlab
7
+ Author: AlterLab
8
+ Author-email: dev@alterlab.io
9
+ Requires-Python: >=3.8,<4.0
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Internet :: WWW/HTTP
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Typing :: Typed
25
+ Requires-Dist: httpx (>=0.24.0)
26
+ Project-URL: Bug Tracker, https://github.com/alterlab/alterlab-python/issues
27
+ Project-URL: Changelog, https://github.com/alterlab/alterlab-python/releases
28
+ Project-URL: Documentation, https://alterlab.io/docs/sdk/python
29
+ Project-URL: Homepage, https://alterlab.io
30
+ Project-URL: Repository, https://github.com/alterlab/alterlab-python
31
+ Description-Content-Type: text/markdown
32
+
33
+ # AlterLab Python SDK
34
+
35
+ Official Python SDK for the [AlterLab Web Scraping API](https://alterlab.io). Extract data from any website with intelligent anti-bot bypass, JavaScript rendering, and structured extraction.
36
+
37
+ [![PyPI version](https://badge.fury.io/py/alterlab.svg)](https://badge.fury.io/py/alterlab)
38
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
39
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
40
+
41
+ ## Features
42
+
43
+ - **Simple API**: 3 lines of code to scrape any website
44
+ - **Intelligent Anti-Bot Bypass**: Automatic tier escalation (curl → HTTP → stealth → browser)
45
+ - **JavaScript Rendering**: Full Playwright browser for JS-heavy sites
46
+ - **Structured Extraction**: JSON Schema, prompts, and pre-built profiles
47
+ - **BYOP Support**: Bring Your Own Proxy for 20% discount
48
+ - **Async Support**: Native asyncio for concurrent scraping
49
+ - **Type Hints**: Full typing support for IDE autocomplete
50
+ - **Cost Controls**: Set budgets, prefer cost/speed, fail-fast options
51
+
52
+ ## Installation
53
+
54
+ ```bash
55
+ pip install alterlab
56
+ ```
57
+
58
+ ## Quick Start
59
+
60
+ ```python
61
+ from alterlab import AlterLab
62
+
63
+ # Initialize client
64
+ client = AlterLab(api_key="sk_live_...") # or set ALTERLAB_API_KEY env var
65
+
66
+ # Scrape a website
67
+ result = client.scrape("https://example.com")
68
+ print(result.text) # Extracted text
69
+ print(result.json) # Structured JSON (Schema.org, metadata)
70
+ print(result.billing.cost_dollars) # Cost breakdown
71
+ ```
72
+
73
+ ## Pricing
74
+
75
+ Pay-as-you-go pricing with no subscriptions. **$1 = 5,000 scrapes** (Tier 1).
76
+
77
+ | Tier | Name | Price | Per $1 | Use Case |
78
+ |------|------|-------|--------|----------|
79
+ | 1 | Curl | $0.0002 | 5,000 | Static HTML sites |
80
+ | 2 | HTTP | $0.0003 | 3,333 | Sites with TLS fingerprinting |
81
+ | 3 | Stealth | $0.0005 | 2,000 | Sites with browser checks |
82
+ | 4 | Browser | $0.001 | 1,000 | JS-heavy SPAs |
83
+ | 5 | Captcha | $0.02 | 50 | Sites with CAPTCHAs |
84
+
85
+ The API automatically escalates through tiers until successful, charging only for the tier used.
86
+
87
+ ## Usage Examples
88
+
89
+ ### Basic Scraping
90
+
91
+ ```python
92
+ from alterlab import AlterLab
93
+
94
+ client = AlterLab(api_key="sk_live_...")
95
+
96
+ # Auto mode - intelligent tier escalation
97
+ result = client.scrape("https://example.com")
98
+
99
+ # Force HTML-only (fastest, cheapest)
100
+ result = client.scrape_html("https://example.com")
101
+
102
+ # JavaScript rendering
103
+ result = client.scrape_js("https://spa-app.com", screenshot=True)
104
+ print(result.screenshot_url)
105
+ ```
106
+
107
+ ### Structured Extraction
108
+
109
+ ```python
110
+ # Extract specific fields with JSON Schema
111
+ result = client.scrape(
112
+ "https://store.com/product/123",
113
+ extraction_schema={
114
+ "type": "object",
115
+ "properties": {
116
+ "name": {"type": "string"},
117
+ "price": {"type": "number"},
118
+ "in_stock": {"type": "boolean"}
119
+ }
120
+ }
121
+ )
122
+ print(result.json) # {"name": "...", "price": 29.99, "in_stock": true}
123
+
124
+ # Or use a pre-built profile
125
+ result = client.scrape(
126
+ "https://store.com/product/123",
127
+ extraction_profile="product"
128
+ )
129
+ ```
130
+
131
+ ### Cost Controls
132
+
133
+ ```python
134
+ from alterlab import AlterLab, CostControls
135
+
136
+ client = AlterLab(api_key="sk_live_...")
137
+
138
+ # Limit to cheap tiers only
139
+ result = client.scrape(
140
+ "https://example.com",
141
+ cost_controls=CostControls(
142
+ max_tier="2", # Don't go above HTTP tier
143
+ prefer_cost=True, # Optimize for lowest cost
144
+ fail_fast=True # Error instead of escalating
145
+ )
146
+ )
147
+
148
+ # Estimate cost before scraping
149
+ estimate = client.estimate_cost("https://linkedin.com")
150
+ print(f"Estimated: ${estimate.estimated_cost_dollars:.4f}")
151
+ print(f"Confidence: {estimate.confidence}")
152
+ ```
153
+
154
+ ### Advanced Options
155
+
156
+ ```python
157
+ from alterlab import AlterLab, AdvancedOptions
158
+
159
+ client = AlterLab(api_key="sk_live_...")
160
+
161
+ # Full browser with screenshot and PDF
162
+ result = client.scrape(
163
+ "https://example.com",
164
+ mode="js",
165
+ advanced=AdvancedOptions(
166
+ render_js=True,
167
+ screenshot=True,
168
+ generate_pdf=True,
169
+ markdown=True,
170
+ wait_condition="networkidle"
171
+ )
172
+ )
173
+
174
+ print(result.screenshot_url)
175
+ print(result.pdf_url)
176
+ print(result.markdown_content)
177
+ ```
178
+
179
+ ### BYOP (Bring Your Own Proxy)
180
+
181
+ Get 20% discount when using your own proxy:
182
+
183
+ ```python
184
+ from alterlab import AlterLab, AdvancedOptions
185
+
186
+ client = AlterLab(api_key="sk_live_...")
187
+
188
+ # Use your configured proxy integration
189
+ result = client.scrape(
190
+ "https://example.com",
191
+ advanced=AdvancedOptions(
192
+ use_own_proxy=True,
193
+ proxy_country="US" # Optional: request specific geo
194
+ )
195
+ )
196
+
197
+ # Check if BYOP was applied
198
+ if result.billing.byop_applied:
199
+ print(f"Saved {result.billing.byop_discount_percent}%!")
200
+ ```
201
+
202
+ ### Async Support
203
+
204
+ ```python
205
+ import asyncio
206
+ from alterlab import AsyncAlterLab
207
+
208
+ async def main():
209
+ async with AsyncAlterLab(api_key="sk_live_...") as client:
210
+ # Single request
211
+ result = await client.scrape("https://example.com")
212
+
213
+ # Concurrent requests
214
+ urls = [
215
+ "https://example.com/page1",
216
+ "https://example.com/page2",
217
+ "https://example.com/page3",
218
+ ]
219
+ results = await asyncio.gather(*[client.scrape(url) for url in urls])
220
+
221
+ for r in results:
222
+ print(r.title, r.billing.cost_dollars)
223
+
224
+ asyncio.run(main())
225
+ ```
226
+
227
+ ### Caching
228
+
229
+ ```python
230
+ # Enable caching (opt-in)
231
+ result = client.scrape(
232
+ "https://example.com",
233
+ cache=True, # Enable caching
234
+ cache_ttl=3600, # Cache for 1 hour
235
+ )
236
+
237
+ if result.cached:
238
+ print("Cache hit - no credits charged!")
239
+
240
+ # Force refresh
241
+ result = client.scrape(
242
+ "https://example.com",
243
+ cache=True,
244
+ force_refresh=True # Bypass cache
245
+ )
246
+ ```
247
+
248
+ ### PDF and Image Extraction
249
+
250
+ ```python
251
+ # Extract text from PDF
252
+ result = client.scrape_pdf(
253
+ "https://example.com/document.pdf",
254
+ format="markdown"
255
+ )
256
+ print(result.text)
257
+
258
+ # OCR for images
259
+ result = client.scrape_ocr(
260
+ "https://example.com/image.png",
261
+ language="eng"
262
+ )
263
+ print(result.text)
264
+ ```
265
+
266
+ ### Error Handling
267
+
268
+ ```python
269
+ from alterlab import (
270
+ AlterLab,
271
+ AuthenticationError,
272
+ InsufficientCreditsError,
273
+ RateLimitError,
274
+ ScrapeError,
275
+ TimeoutError
276
+ )
277
+
278
+ client = AlterLab(api_key="sk_live_...")
279
+
280
+ try:
281
+ result = client.scrape("https://example.com")
282
+ except AuthenticationError:
283
+ print("Invalid API key")
284
+ except InsufficientCreditsError:
285
+ print("Please top up your balance")
286
+ except RateLimitError as e:
287
+ print(f"Rate limited. Retry after {e.retry_after}s")
288
+ except ScrapeError as e:
289
+ print(f"Scraping failed: {e.message}")
290
+ except TimeoutError:
291
+ print("Request timed out")
292
+ ```
293
+
294
+ ### Check Usage & Balance
295
+
296
+ ```python
297
+ usage = client.get_usage()
298
+ print(f"Balance: ${usage.balance_dollars:.2f}")
299
+ print(f"Used this month: {usage.credits_used_month} credits")
300
+ ```
301
+
302
+ ## API Reference
303
+
304
+ ### AlterLab Client
305
+
306
+ ```python
307
+ AlterLab(
308
+ api_key: str = None, # API key (or ALTERLAB_API_KEY env var)
309
+ base_url: str = None, # Custom API URL
310
+ timeout: int = 120, # Request timeout in seconds
311
+ max_retries: int = 3, # Retry count for transient failures
312
+ retry_delay: float = 1.0 # Initial retry delay (exponential backoff)
313
+ )
314
+ ```
315
+
316
+ ### scrape() Method
317
+
318
+ ```python
319
+ client.scrape(
320
+ url: str, # URL to scrape
321
+ mode: str = "auto", # "auto", "html", "js", "pdf", "ocr"
322
+ sync: bool = True, # Wait for result vs return job ID
323
+ advanced: AdvancedOptions, # Advanced scraping options
324
+ cost_controls: CostControls, # Budget and optimization settings
325
+ cache: bool = False, # Enable response caching
326
+ cache_ttl: int = None, # Cache TTL in seconds (60-86400)
327
+ formats: list = None, # Output formats: ["text", "json", "html", "markdown"]
328
+ extraction_schema: dict, # JSON Schema for structured extraction
329
+ extraction_prompt: str, # Natural language extraction instructions
330
+ extraction_profile: str, # Pre-built profile: "product", "article", etc.
331
+ wait_for: str = None, # CSS selector to wait for (JS mode)
332
+ screenshot: bool = False, # Capture screenshot (JS mode)
333
+ ) -> ScrapeResult
334
+ ```
335
+
336
+ ### ScrapeResult
337
+
338
+ ```python
339
+ result.url # Scraped URL
340
+ result.status_code # HTTP status
341
+ result.text # Extracted text content
342
+ result.html # HTML content
343
+ result.json # Structured JSON content
344
+ result.title # Page title
345
+ result.author # Author (if detected)
346
+ result.billing # BillingDetails object
347
+ result.billing.tier_used # Tier that succeeded
348
+ result.billing.cost_dollars # Final cost in USD
349
+ result.screenshot_url # Screenshot URL (if requested)
350
+ result.pdf_url # PDF URL (if requested)
351
+ result.cached # Whether result was from cache
352
+ ```
353
+
354
+ ## Environment Variables
355
+
356
+ | Variable | Description |
357
+ |----------|-------------|
358
+ | `ALTERLAB_API_KEY` | Your API key (alternative to passing in constructor) |
359
+
360
+ ## Requirements
361
+
362
+ - Python 3.8+
363
+ - httpx >= 0.24.0
364
+
365
+ ## Support
366
+
367
+ - **Documentation**: [https://alterlab.io/docs](https://alterlab.io/docs)
368
+ - **API Status**: [https://status.alterlab.io](https://status.alterlab.io)
369
+ - **Support**: support@alterlab.io
370
+ - **Issues**: [GitHub Issues](https://github.com/alterlab/alterlab-python/issues)
371
+
372
+ ## License
373
+
374
+ MIT License - see [LICENSE](LICENSE) for details.
375
+
@@ -0,0 +1,5 @@
1
+ alterlab/__init__.py,sha256=YrOb55dxqsQATdcmUdulBGG2iE2ZuLmD2qceCrh12Xo,1471
2
+ alterlab/client.py,sha256=qcbz4KwsxloUpvNVeRfPU0I4NNy_2SeXNC-fgoc3LTY,45436
3
+ alterlab-2.0.0.dist-info/METADATA,sha256=Q8uqV2fRkiBotnIirlICX2BdSQfVGPR965QI3oByKJQ,10903
4
+ alterlab-2.0.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
5
+ alterlab-2.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.2.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any