Skip to main content

Ani Scrapy

PyPI Version

License

⚠️ Disclaimer

Warning: This library is intended for educational and personal use only. Please respect the terms of service of the websites being scraped and the applicable laws. The author is not responsible for any misuse.

Ani-Scrapy is a Python async-first library for scraping anime websites. It makes easy to switch between different platforms.

Ani-Scrapy helps developers automate anime downloads and build applications. It provides detailed anime and episode information, along with download links from multiple servers, supporting dynamic and static content across several sites.

🚀 Features

Core Functionality

  • Async-First Design: Built from the ground up for asynchronous Python
  • Multi-Platform Support: Unified interface for different platforms
  • Comprehensive Data: Detailed anime metadata, episode information, and download links

Content Handling

  • Static Content Extraction: Direct server links using aiohttp and BeautifulSoup
  • Dynamic Content Processing: JavaScript-rendered links using Playwright
  • Mixed Approach: Smart fallback between static and dynamic methods

Technical Capabilities

  • Concurrent Scraping: Built-in support for asynchronous batch processing
  • Automatic Resource Management: Browser instances handled automatically
  • Custom Browser Support: Configurable browser paths via executable_path

Development Experience

  • Modular Design: Easy to extend with new scrapers and platforms
  • Logging: Uses Loguru; respects global configuration
  • Performance Optimization: Connection reuse and caching capabilities

📦 Installation

From PyPI:

pip install ani-scrapy

🐍 Requirements

  • Python >= 3.10.14

Install browser (only once):

playwright install chromium

Recommendation: Use Brave browser for sites with excessive advertising. See Custom Browser below.

🔍 Diagnostics

Run the diagnostic tool to check your environment:

ani-scrapy doctor

This checks:

  • Python version and platform
  • Playwright and Chromium available
  • Brave browser (recommended for sites with ads)
  • Network connectivity to supported sites (JKAnime, AnimeAV1)

Options

ani-scrapy doctor --output json  # JSON output for CI/CD
ani-scrapy doctor --timeout 10   # Increase timeout for slow connections

Exit Codes

Code Meaning
0 All checks passed
1 Warnings found
2 Errors found

📝 Logging

Ani-Scrapy uses Loguru for all logging. By default, logging is silent (no output). To enable logging, use the enable_logging() function.

Enable Logging

from ani_scrapy import AnimeFLVScraper, enable_logging

enable_logging(level="DEBUG")  # Enable with DEBUG level to stdout

async with AnimeFLVScraper() as scraper:
    await scraper.log("naruto")

Custom Configuration

You can customize the log output:

from ani_scrapy import enable_logging

# Log to file
enable_logging(level="INFO", sink="ani_scrapy.log")

# Log to stdout with custom level
enable_logging(level="DEBUG", sink=None)  # None = stdout

You can configure a custom browser executable path. Brave is recommended because its native ad-blocker reduces blocking on sites with excessive advertisements, but any Chromium-based browser (Chrome, Chromium, Edge) will work.

Benefits of Brave

  • Native Ad-Block: Built-in protection reduces detection probability
  • Avoids Captchas: Sites with aggressive ads may fail with Chromium's default configuration
  • Better Success Rate: Sites with excessive advertising can fail or timeout with the default browser

Configuration

from ani_scrapy import AnimeFLVScraper

brave_path = "C:/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe"

async with AnimeFLVScraper(executable_path=brave_path) as scraper:
    info = await scraper.get_anime_info(anime_id="anime-id")

📖 API Reference

For complete documentation: Docs index

Methods Overview:

  • search_anime - Search for anime
  • get_anime_info - Get detailed anime information
  • get_table_download_links - Get direct server links
  • get_iframe_download_links - Get iframe links
  • get_file_download_link - Get final download URL
  • get_new_episodes - Get new episodes since last known

Scraper Classes:

  • AnimeFLVScraper - Scraper for AnimeFLV (deprecated: the site moved to https://animeflv.or.at/ with a different structure and the provider no longer works; it emits a DeprecationWarning and will be removed in a future version)
  • JKAnimeScraper - Scraper for JKAnime
  • AnimeAV1Scraper - Scraper for AnimeAV1. schedule_cache_ttl (seconds, default None = never expires) controls how long the /horario schedule is cached

Method Status Comparison

Method AnimeFLV JKAnime AnimeAV1
search_anime ✅ Static ✅ Static ✅ Static
get_anime_info ✅ Static ⚠️ Dynamic ✅ Static
get_new_episodes ✅ Static ⚠️ Dynamic ✅ Static
get_table_download_links ✅ Static ⚠️ Dynamic ✅ Static
get_iframe_download_links ⚠️ Dynamic ⚠️ Dynamic ✅ Static
get_file_download_link ⚠️ Dynamic ⚠️ Dynamic ⚠️ Dynamic

Legend:

  • ✅ Static: Method works without browser (HTTP only)
  • ⚠️ Dynamic: Method requires browser (Playwright)

Performance Benchmark

Test conditions: Anime "Gachiakuta", Episode 24, Query: "gach" (2026-04-12)

Provider search_anime get_anime_info get_table_download_links get_iframe_download_links
AnimeFLV 316.18 ms 849.96 ms 251.40 ms 5070.68 ms
JKAnime 468.76 ms 30945.13 ms 1661.44 ms 8802.14 ms
AnimeAV1 517.24 ms 355.09 ms 298.78 ms 299.14 ms

Browser Classes:

  • AsyncBrowser - Manual browser control for advanced use cases

🛠️ Advanced Usage

Browser Usage Patterns

The library supports 3 ways to manage the browser for JavaScript-rendered content.

1. Automatic (Default)

The browser is created automatically when needed and reused within the same context. Functions like get_anime_info, get_table_download_links, etc. will open the browser if not already open, or reuse it if another function already opened it within the same async with block:

import asyncio
from ani_scrapy import JKAnimeScraper

async def main():
    async with JKAnimeScraper() as scraper:
        # get_anime_info opens the browser internally
        info = await scraper.get_anime_info("gachiakuta", include_episodes=True)
        # get_table_download_links reuses the same browser
        links = await scraper.get_table_download_links("gachiakuta", episode=1)
    # Browser automatically closed when exiting context

asyncio.run(main())

2. Manual Start/Stop

Use this pattern when you need explicit control over the browser lifecycle without using async with, or for programmatic usage. All functions in the scraper will use the same manually opened browser:

import asyncio
from ani_scrapy import JKAnimeScraper

async def scrape_anime(anime_id: str):
    scraper = JKAnimeScraper()

    await scraper.start_browser()  # Open browser explicitly

    # All functions use the same browser instance
    info = await scraper.get_anime_info(anime_id, include_episodes=True)
    links = await scraper.get_table_download_links(anime_id, episode=1)
    final_url = await scraper.get_file_download_link(links.download_links[0])

    await scraper.stop_browser()  # Close browser explicitly
    await scraper.aclose()         # Close scraper resources

asyncio.run(scrape_anime("gachiakuta"))

3. External Browser Injection

Use an externally created AsyncBrowser instance. All scraper functions will use the injected browser:

import asyncio
from ani_scrapy import AsyncBrowser, JKAnimeScraper

async def main():
    # Create browser with custom executable
    brave_path = "C:/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe"

    async with AsyncBrowser(headless=True, executable_path=brave_path) as browser:
        # Inject external browser into scraper
        async with JKAnimeScraper(external_browser=browser) as scraper:
            # All functions use the injected browser
            info = await scraper.get_anime_info("gachiakuta")
            print(f"Title: {info.title}")
        # Browser stays open - controlled externally

asyncio.run(main())

When to Use Each Pattern

Pattern Use Case
1. Automatic Most cases - simple and automatic
2. Manual Programmatic use without async with, fine-grained control
3. External Share browser across scrapers, custom browser config

Concurrent Scraping

import asyncio

async def scrape_multiple_animes(anime_ids, scraper):
    tasks = []
    for anime_id in anime_ids:
        task = scraper.get_anime_info(anime_id)
        tasks.append(task)

    results = await asyncio.gather(*tasks, return_exceptions=True)
    return results

📄 License

MIT © 2025 El Pitágoras

Metadata

Release files for ani-scrapy 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ani-scrapy 0.8.0
File Size Uploaded
ani_scrapy-0.8.0.tar.gz 38.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ani-scrapy 0.8.0
File Interpreter ABI Platform
ani_scrapy-0.8.0-py3-none-any.whl Python 3 none any Details

Total release size: 77.8 kB

Release files / ani_scrapy-0.8.0.tar.gz

Download URL ani_scrapy-0.8.0.tar.gz
Size 38.6 kB
Tags Source
SHA-256 checksum
How to use checksums
c5bb4e485fad0abb51f8fe12a4529c5266913f58b65607191c447c1ead1d4beb
BLAKE2b-256 checksum
How to use checksums
1f7cbf3907b6471ec9cc191dc40b3e807d7ff06c89f8429a58ac767ada4789dc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / ani_scrapy-0.8.0-py3-none-any.whl

Download URL ani_scrapy-0.8.0-py3-none-any.whl
Size 39.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fae3c2ff3bedb9a25dc178114ac3839fdec90e76118427e8919b8f68d39dc9e8
BLAKE2b-256 checksum
How to use checksums
a9a076ad92c5b411cab7d424628c9231241f01acb1c009309edcf75ceb90f8b5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.8.1

2 release files

This release

0.8.0 This release

2 release files

0.7.0

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.23

2 release files

0.1.22

2 release files

0.1.21

2 release files

0.1.19

2 release files

0.1.18

2 release files

0.1.17

2 release files

0.1.16

2 release files

0.1.15

2 release files

0.1.14

2 release files

0.1.13

2 release files

0.1.12

2 release files

0.1.11

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page