Python Async v2.4.1

SpankBang API

A fully asynchronous Python API wrapper and scraper for SpankBang. Fetch videos, metadata, search, and iterate over channels, creators, or pornstars. Download content using HLS or direct RAW MP4 downloads. Powered by the eaf_base_api networking engine.

GitHub
⚡ Recommended AI Workflow Official MCP Server: https://mcp.echteralsfake.me/mcp

Supercharge your development by connecting your AI coding assistant (Cursor, VS Code / Copilot, Claude Desktop, Windsurf, Zed, Antigravity). No authentication required · No strict rate limits · Covers all 16 APIs · Always up to date · Completely anonymous (0 logs, no profiling). Connecting this MCP server to your AI assistant is absolutely the recommended way to work on and build with these APIs.

⚠️ Legal Disclaimer
This tool is an unofficial, independent project and is not affiliated with, endorsed by, or sponsored by the target website. This software is provided "as is" for educational and personal purposes only. The developer assumes no responsibility for any consequences arising from the use of this tool, including but not limited to account suspension, IP blocking, or any violation of the target website's Terms of Service. Users are solely responsible for ensuring their use complies with all applicable laws and policies. Use at your own risk.
💚 Support & Commercial Licensing
If you find this project helpful, please consider donating to support its continued development!

Other Options:
• PayPal
• Ko-Fi

For extended features, enterprise integrations, or custom commercial licensing, please contact EchterAlsFakeBS@proton.me.

📦 Installation

Install from PyPI using pip:

bash
pip install unofficial-api-for-spankbang

For TS→MP4 remuxing support (recommended for HLS downloads), install with the optional av dependency:

bash
pip install unofficial-api-for-spankbang[av]
Note
Requires Python ≥ 3.12. eaf_base_api ≥ 4.0.0 is installed automatically as a dependency.

🚀 Quick Start

Every method in this API is asynchronous. You need to run your code inside an async function:

python
import asyncio
from spankbang_api import Client

async def main():
    client = Client()

    # Fetch a video
    video = await client.get_video("https://spankbang.com/...")

    # Access metadata
    print(video.title)
    print(video.length)
    print(video.video_qualities)

    # Download the video using HLS (default)
    from base_api import DownloadConfigHLS
    config = DownloadConfigHLS(quality="best", path="./downloads")
    await video.download(configuration_hls=config, use_hls=True)

asyncio.run(main())

⚙️ Configuration

The API uses eaf_base_api ≥ 4.0.0. Configure its singular proxy, bounded request attempts, timeouts, and other runtime behavior through the BaseCore passed to Client.

Please refer to the eaf_base_api Documentation for the complete reference on how to set up RuntimeConfig and properly integrate it with this API.

The current client sets RuntimeConfig.http_version to "v3" before initializing its session and installs SpankBang's required Origin/Referer headers. Pass a core whose session has not already been initialized so the HTTP/3 setting takes effect.

python
from base_api import BaseCore
from base_api.modules.config import RuntimeConfig
from spankbang_api import Client

my_config = RuntimeConfig()
my_config.proxy = "socks5://127.0.0.1:9050"
my_config.request_attempts = 3

core = BaseCore(configuration=my_config)
client = Client(core=core)

🔌 Client

The Client class manages the network session, cookies, and HTTP headers to interact with SpankBang. It serves as the primary entry point to retrieve video details, explore profile channels/pornstars/creators, and run search queries.

python
from spankbang_api import Client
from base_api import BaseCore

client = Client()

# Or construct with custom core configuration
client_custom = Client(core=BaseCore())

Constructor Parameters

  • core BaseCore — Networking core instance (default: BaseCore(RuntimeConfig()))

Methods

Fetch Video get_video()

async
Fetches a video page and returns a populated Video object. Parses Javascript variables containing HLS master playlists and direct MP4 resolutions.
await client.get_video( url: str, load_html: bool = True ) -> Video

Parameters

  • url str — The full SpankBang video URL
  • load_html bool — If True (default), fetches and parses the HTML page for metadata

Returns

→ Video

Fetch Channel get_channel()

async
Fetches a channel profile page and returns a populated Channel object.
await client.get_channel( url: str, load_html: bool = True ) -> Channel

Parameters

  • url str — The full SpankBang channel URL
  • load_html bool — If True (default), parses the profile HTML for metadata

Returns

→ Channel

Fetch Pornstar get_pornstar()

async
Fetches a pornstar profile page and returns a populated Pornstar object.
await client.get_pornstar( url: str, load_html: bool = True ) -> Pornstar

Parameters

  • url str — The full SpankBang pornstar URL
  • load_html bool — If True (default), parses the profile HTML for metadata

Returns

→ Pornstar

Fetch Creator get_creator()

async
Fetches a creator profile page and returns a populated Creator object.
await client.get_creator( url: str, load_html: bool = True ) -> Creator

Parameters

  • url str — The full SpankBang creator URL
  • load_html bool — If True (default), parses the profile HTML

Returns

→ Creator

Search Videos search()

async
Performs a search query for videos with options to filter by rating, quality, duration, and upload date. Yields results paginated. See Search & Filtering.
async for result in client.search( query, filter: Literal["trending", "new", "featured", "popular"] | None = None, quality: Literal["hd", "fhd", "uhd"] | None = None, duration: Literal["10", "20", "40"] | None = None, date: Literal["d", "w", "m", "y"] | None = None, pages: int = 2, iterator_config: IteratorConfig | None = None ) -> AsyncGenerator[ScrapeResult[Video], None]

Parameters

  • query str — Search query keywords
  • filter str | None — Filter order: "trending", "new", "featured", "popular"
  • quality str | None — Quality filter: "hd" (720p), "fhd" (1080p), "uhd" (4k)
  • duration str | None — Duration limits: "10" (10+ min), "20" (20+ min), "40" (40+ min)
  • date str | None — Upload date range: "d" (day), "w" (week), "m" (month), "y" (year)
  • pages int — Number of pages to iterate (default: 2)
  • iterator_config IteratorConfig | None — Optional v4 concurrency, ordering, eager-source, retry, and error-handling policy. The package default eagerly loads html.

Returns

→ AsyncGenerator[ScrapeResult[Video], None]

🎬 Video

dataclass Inherits from BaseMedia. Represents a single SpankBang video. Populated with metadata from parsed Javascript configurations (stream_data) on the page and standard HTML tags.

Attributes

AttributeTypeDescription
urlstrThe video page URL
titlestr | NoneVideo title
descriptionstr | NoneDescription metadata content
thumbnailstr | NoneVideo preview cover image URL
tagslist | NoneList of tags/categories
authorstr | NoneAuthor / channel publisher name
imagestr | NoneAuthor profile thumbnail / image alt text
ratingstr | NoneUpvote percentage (e.g. 92%)
lengthstr | NoneLength in seconds
m3u8_base_urlstr | NoneHLS master playlist URL
direct_download_urlslist | NoneCDN-resolved direct MP4 URLs
video_qualitieslist[str] | NoneSorted list of available resolution heights (e.g. ["240", "320", "480", "720", "1080", "4k"])
Scraper Iterator Fallback Attributes
tagstr | NonePrimary search tag associated with the item
viewsstr | NoneView count string from the listing card
resolutionstr | NoneMaximum resolution badge from listing card
video_source_urlstr | NoneRaw listing element fallbacks

Methods

Download Video download()

async
Downloads the video. Supports downloading via HLS segments (default) or fetching direct CDN MP4 files depending on the use_hls parameter. Ordinary failures raise DownloadFailed with full diagnostic context and chained cause.
await video.download( configuration_hls: DownloadConfigHLS | None = None, configuration_raw: DownloadConfigRAW | None = None, use_hls: bool = True ) -> bool | DownloadReport

Parameters

  • configuration_hls DownloadConfigHLS | None — Config options for HLS segment downloads. Used if use_hls=True.
  • configuration_raw DownloadConfigRAW | None — Config options for direct file downloads. Used if use_hls=False.
  • use_hls bool — Download via HLS (default: True). Set False to download via raw MP4 links.

Returns

→ bool | DownloadReport

⭐ Pornstar / Channel / Creator

dataclass Inherits from PornstarHelper → BaseMedia. Under the hood, SpankBang profiles for Pornstar, Channel, and Creator share the same attributes and methods via a common base class.

Attributes

AttributeTypeDescription
urlstrThe profile base URL
namestr | NoneName of the pornstar, channel, or creator
video_countstr | NoneTotal uploaded/featured videos
views_countstr | NoneTotal profile views
subscribers_countstr | NoneTotal subscriber count
imagestr | NoneProfile avatar cover image URL

Methods

Get Profile Videos videos()

async
Asynchronously yields video items listed on this profile, navigating page-by-page.
async for result in profile.videos( pages: int = 0, iterator_config: IteratorConfig | None = None ) -> AsyncGenerator[ScrapeResult[Video], None]

Parameters

  • pages int — Number of extra pages to fetch (0 means only the main page URL)
  • iterator_config IteratorConfig | None — Optional v4 iterator policy. The default eagerly loads each video's html source.

Returns

→ AsyncGenerator[ScrapeResult[Video], None]

🔍 Search & Filtering

Perform advanced searches on SpankBang by passing filter keywords to the `client.search()` generator:

python
# Search for popular 1080p videos uploaded this week
async for result in client.search(
    query="college",
    filter="popular",
    quality="fhd",     # 1080p resolution
    date="w",           # weekly
    pages=3
):
    if result.succeeded:
        video = result.unwrap()
        print(video.title, video.url)

Filter Parameters Map

Sort/Filter (filter)

ValueDescription
"trending"Trending videos (Default option)
"new"Most recent videos
"featured"Featured videos
"popular"Most popular videos

Quality (quality)

ValueTarget Quality
"hd"High Definition (720p)
"fhd"Full High Definition (1080p)
"uhd"Ultra High Definition (4k resolution)

Duration (duration)

ValueTarget Range
"10"Videos longer than 10 minutes
"20"Videos longer than 20 minutes
"40"Videos longer than 40 minutes

Date Range (date)

ValueTimeline
"d"Uploaded today
"w"Uploaded this week
"m"Uploaded this month
"y"Uploaded this year

⬇️ Downloading Options

SpankBang supports dual download configurations. Under the hood, the master playlist contains an HLS stream, but direct CDN links are also extracted if you prefer RAW MP4 chunked downloading.

HLS Download (Recommended)

HLS provides highly reliable stream downloads, slicing chunked `.ts` packages and remuxing them to `.mp4` via PyAV:

python
from base_api import DownloadConfigHLS

config = DownloadConfigHLS(
    quality="best",
    path="./downloads"
)
success = await video.download(configuration_hls=config, use_hls=True)

RAW CDN Download

RAW downloads request full files directly from SpankBang's media CDN servers, leveraging HTTP range requests to speed up the process across parallel workers:

python
from base_api import DownloadConfigRAW

config = DownloadConfigRAW(
    quality="best",          # "best", "half", "worst"
    path="./downloads",
    allow_multipart=True,
    max_workers=5
)
success = await video.download(configuration_raw=config, use_hls=False)

📄 Pagination & Iterators

All listings (such as client.search() and profile.videos()) yield typed ScrapeResult[Video] values. Use succeeded to branch safely or unwrap() to return the item and raise its terminal error on failure:

python
async for result in client.search("solo", pages=2):
    if result.succeeded:
        video = result.unwrap()
        print(video.title)
    else:
        print(result.stage, result.url, result.error)

ScrapeResult Properties

AttributeTypeDescription
stageScrapeStageWhether the result came from the page or item stage
urlstrThe video item page URL
page_indexintZero-based source page index
item_indexint | NoneZero-based item index, or None for a page failure
attemptsintNumber of attempts used by the yielding stage
itemVideo | NonePopulated video on success
errorScrapeOperationError | NoneTyped terminal page or item error on failure
succeededboolTrue when error is None

IteratorConfig, bounded retries, and custom handlers

All iterator-only controls now live in one IteratorConfig. SpankBang's package default uses ErrorMode.SKIP for terminal page failures; a supplied config replaces that behavior, and a bare IteratorConfig instead defaults to ErrorMode.YIELD. A retry policy's max_attempts includes the initial attempt, so this example makes at most three stage attempts per failed page or item. Each stage attempt may itself perform the request retries configured on BaseCore. Fully populated results require the html source.

Leave page_retry or item_retry as None to derive that stage's bounded policy from the active RuntimeConfig request-attempt and backoff settings; an explicit RetryPolicy overrides it per stage.

python
from base_api import ErrorAction, RetryPolicy, ScrapeErrorContext
from base_api.modules.config import IteratorConfig

async def handle_scrape_error(context: ScrapeErrorContext) -> ErrorAction:
    if context.attempt < context.max_attempts:
        return ErrorAction.RETRY
    return ErrorAction.YIELD

retry = RetryPolicy(
    max_attempts=3, base_delay=0.5, multiplier=2.0,
    max_delay=4.0, jitter=0.2
)
iterator_config = IteratorConfig(
    max_page_concurrency=2,
    max_item_concurrency=8,
    max_pending_items=16,
    load_specific_sources=("html",),
    page_retry=retry,
    item_retry=retry,
    page_error_handler=handle_scrape_error,
    item_error_handler=handle_scrape_error,
)

async for result in client.search(
    "solo", pages=2, iterator_config=iterator_config
):
    if result.succeeded:
        print(result.unwrap().title)
    else:
        print(result.stage, result.error)

ScrapeErrorContext supplies stage, url, error, attempt, max_attempts, page_index, and item_index. A handler returns ErrorAction.RETRY, RAISE, YIELD, or SKIP.

Independent page and item handlers

The core routes page-stage failures to page_error_handler and item-stage failures to item_error_handler. Assign the same callable to both fields only when both stages should use the same policy; otherwise configure either handler independently.

⚠️ Error Handling

Source loaders translate request failures into exceptions from spankbang_api.modules.errors. Calls that load media expose ordinary loader failures through base_api.MediaLoadError (or MediaLoadErrors for several sources); inspect original_error/errors as shown. Operations outside media loading may still raise package or core exceptions directly.

Request and download failures are logged with the operation, target URL, and full original traceback. Translated exceptions retain the original error in __cause__. Download preparation failures (including metadata loading, quality selection, and output path setup) are also wrapped in DownloadFailed; inspect its cause when diagnosing a failure. The specific availability exceptions listed below remain supported. An explicit DownloadCancelled or asyncio.CancelledError propagates without being wrapped in DownloadFailed. Base downloader False and DownloadReport results remain supported; inspect the result as well as handling exceptions.

The common provider errors NotFound, NetworkError, BotDetection, ProxyError, UnknownNetworkError, and DownloadFailed are catchable through base_api.modules.errors. They derive from ScraperException, which now derives from BaseScraperError. Existing provider import paths remain valid.

See Logging & Cleanup for application logging setup.

VideoIsProcessing derives from ScraperException and now has a non-empty default exception message. HLS and RAW download failures both retain their causes; a ResourceGone raised during downloading is translated to VideoUnavailable with the video URL.

ExceptionTrigger Cause
NotFoundServer returned HTTP 404 (e.g. video deleted)
NetworkErrorRequest failed due to a network error, exhausted request retries, or a non-404 HTTPStatusError
BotDetectionBot-protection challenge block detected
ProxyErrorProxy connection failed
VideoIsProcessingThe video is still processing on SpankBang's servers
VideoUnavailableVideo stream is unavailable from SpankBang
DownloadFailedDownload preparation or transfer failed; the video URL is included and __cause__ retains the original exception
python
from base_api import MediaLoadError
from spankbang_api.modules.errors import VideoIsProcessing, NotFound

try:
    video = await client.get_video(url)
except MediaLoadError as error:
    if isinstance(error.original_error, VideoIsProcessing):
        print("This video is still processing!")
    elif isinstance(error.original_error, NotFound):
        print("Video no longer exists.")
    else:
        raise

📝 Changelog

2.4.1 — 2026-09-15

  • 35024f6 / 9ab9185 — Adopted shared request and download error handling with base_api.modules.provider (requiring eaf-base-api>=4.2.0). Failed downloads now raise DownloadFailed with complete context. Added 4K resolution support (sorted as 2160p) for video scraping and downloads. Upgraded scraper selectors across video, channel, creator, and pornstar pages with robust fallbacks and data-testid attributes. Enhanced stream_data regex parsing and added offline extraction unit tests.

2.4.1 — 2026-08-14

  • 18a8f15 / 5871e80 — Updated request headers and forced HTTP/3 for newly initialized client sessions to restore access after upstream 403 responses.

2.3 — 2026-08-11

  • 809909a / 71e71f6 — Added the PEP 561 py.typed marker, left iterator retry policies unset so they resolve from RuntimeConfig, and removed a temporary local package-source setting from the published configuration.

2.3 — 2026-08-08

  • e63c384 — Consolidated profile and search iterator concurrency, ordering, source loading, retry, and error controls into IteratorConfig.

2.3 migration — 2026-08-07

  • 2f1c01d — Migrated to the eaf_base_api v4 request and scraping model: fetch_text()/request(), structured exceptions, source-aware media loading, typed scrape streams/results, bounded retries, and field-aware loading before downloads.

💻 CLI Usage

The CLI entry point configures console logging at INFO level. Caught per-URL failures include the URL and full traceback; the default log format shows the logger, file, line, and function. Library applications should configure logging once at startup.

SpankBang API includes a command-line interface accessible via spankbang_api or python -m spankbang_api:

bash
# Download a single video
spankbang_api --download "https://spankbang.com/12345/video/sample" --quality best --output ./downloads --no-title False

# Or invoke via python -m
python -m spankbang_api --download "https://spankbang.com/12345/video/sample" --quality best --output ./downloads --no-title False

# Download from a line-separated file of URLs
spankbang_api --file urls.txt --quality best --output ./downloads --no-title False

CLI Options

FlagDescription
--download URLVideo URL to download
--file FILEText file with URLs (separated by newlines)
--quality QUALITYVideo quality: best, half, worst
--output DIRDestination directory or output file path
--no-title True/FalseSkip auto-appending video title to output filename (default: False)

🖥️ Supported Platforms

PlatformArchitectureStatus
Windows 11x64✅ Tested
macOS Sequoiax86_64✅ Tested
Linux (Arch)x86_64✅ Tested
Android 16aarch64✅ Tested