Specter
Specter is a highly resilient, high-performance Python library designed for robust image downloading. It implements a multi-tier fallback pipeline to address restrictive network configurations, anti-scraping protections (Cloudflare), TLS fingerprinting, and hotlinking restrictions.
Features
- Multi-Tier Fallback Pipeline: Sequentially attempts multiple download strategies (Direct, DPI-Resilient proxy, Browser-rendering, and Cache-proxy) to ensure successful retrieval.
- DPI Resilience via ClientHello Segmentation: Implements a local loopback proxy that segments the TLS ClientHello packet, helping resolve network connection limitations.
- Domain Strategy Caching: Thread-safe caching mechanism that stores the successful strategy for each domain, skipping slow timeouts and retries on subsequent requests.
- Thread-Local Connection Pooling: Reuses TCP and TLS connections via Keep-Alive sessions per thread to achieve sub-100ms request times.
- Parallel Batch Downloading: Supports concurrent downloading of multiple images using a built-in ThreadPoolExecutor.
- Headless Browser Fallback: Integrates headless Chromium rendering (via DrissionPage) as a fallback to extract images from canvas elements or screenshots.
Installation
Standard Installation
pip install NullGazeX
Full Installation (with Headless Browser support)
pip install NullGazeX[full]
Quick Start
1. Download a Single Image
from specter import download_image
# Download an image with automatic header and referrer matching
download_image(
url="https://example.com/images/photo.jpg",
output_path="outputs/photo.jpg",
verbose=True
)
2. Concurrent Batch Downloading
To download multiple images concurrently at maximum speed, use the batch downloading interface:
from specter import download_images
# Define a list of targets (url, output_path)
targets = [
("https://example.com/img1.jpg", "outputs/img1.jpg"),
("https://example.com/img2.jpg", "outputs/img2.jpg"),
("https://example.com/img3.jpg", "outputs/img3.jpg")
]
# Run concurrent downloads (default max_workers is 20)
results = download_images(targets, max_workers=10, verbose=True)
for i, res in enumerate(results):
if isinstance(res, Exception):
print(f"Failed to download image {i+1}: {res}")
else:
print(f"Successfully saved to: {res}")
3. Advanced Custom Configuration
You can customize headers or use the object-oriented API directly:
from specter import ImageDownloader
downloader = ImageDownloader(verbose=True)
custom_headers = {
"Referer": "https://custom-referer.com/",
"Cookie": "session_token=xyz123"
}
# Download using the custom downloader instance
downloader.download(
url="https://example.com/protected/image.png",
output_path="outputs/image.png",
headers=custom_headers
)
Technical Specifications & Strategies
| Tier | Strategy | Description | Recommended Case |
|---|---|---|---|
| 1 | Direct Request | Sends a standard HTTP GET with dynamically generated browser headers. | Open networks and unrestricted servers. |
| 2 | DPI Resilience (Split Proxy) | Routes request through a local background proxy that segments the TLS handshake packets to handle strict filters. | ISP-level filters and strict configurations. |
| 3 | Headless Browser | Spawns a headless Chromium instance to render the page and extract the image canvas or take screenshots. | Cloudflare Turnstile or JS challenges. |
| 4 | Weserv Proxy Fallback | Routes requests through a high-availability public image cache proxy. | General availability fallbacks. |
License
This project is licensed under the MIT License. See LICENSE for details.
Metadata
Release files for NullGazeX 2.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| nullgazex-2.2.1.tar.gz | 14.5 kB | Without provenance | Details for nullgazex-2.2.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| nullgazex-2.2.1-py3-none-any.whl | Python 3 | none | any | Details for nullgazex-2.2.1-py3-none-any.whl |
Total release size: 29.8 kB
Release files / nullgazex-2.2.1.tar.gz
| Download URL | nullgazex-2.2.1.tar.gz |
|---|---|
| Size | 14.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a8f8fb82fd90fbfb05eb9eb7443f3eddcff71adbe9a11184f220cfed2d820610
|
|
BLAKE2b-256 checksum How to use checksums |
835d794840c9ac06f77b10ef0f83b3e4c0c2030d07c408f248752800f64bd97e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.10
|
Release files / nullgazex-2.2.1-py3-none-any.whl
| Download URL | nullgazex-2.2.1-py3-none-any.whl |
|---|---|
| Size | 15.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ef0f7c030c2a4791b969c45a8d2b53a1d93c288567f3c9beafb47c3bd475bc68
|
|
BLAKE2b-256 checksum How to use checksums |
6b9aadbb48eab291956ff717b8d3a22eba66daf5856c4b4e6319d15e82d1e591
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.10
|
Security for NullGazeX 2.2.1
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.