{"id":37066477,"url":"https://github.com/stefanodvx/crunpyroll","last_synced_at":"2026-01-14T07:48:17.084Z","repository":{"id":42072820,"uuid":"428773886","full_name":"stefanodvx/crunpyroll","owner":"stefanodvx","description":"Async API wrapper for Crunchyroll","archived":false,"fork":false,"pushed_at":"2024-09-17T12:22:36.000Z","size":360,"stargazers_count":83,"open_issues_count":10,"forks_count":27,"subscribers_count":6,"default_branch":"main","last_synced_at":"2026-01-07T07:38:49.146Z","etag":null,"topics":["anime","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stefanodvx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-11-16T18:38:48.000Z","updated_at":"2025-12-09T13:49:06.000Z","dependencies_parsed_at":"2024-01-06T02:23:43.243Z","dependency_job_id":"e47ebc1f-c9a9-4785-b155-937d232b2b89","html_url":"https://github.com/stefanodvx/crunpyroll","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/stefanodvx/crunpyroll","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefanodvx%2Fcrunpyroll","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefanodvx%2Fcrunpyroll/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefanodvx%2Fcrunpyroll/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefanodvx%2Fcrunpyroll/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stefanodvx","download_url":"https://codeload.github.com/stefanodvx/crunpyroll/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefanodvx%2Fcrunpyroll/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28413496,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T05:26:33.345Z","status":"ssl_error","status_checked_at":"2026-01-14T05:21:57.251Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anime","python"],"created_at":"2026-01-14T07:48:16.590Z","updated_at":"2026-01-14T07:48:17.061Z","avatar_url":"https://github.com/stefanodvx.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/stefanodvx/crunpyroll\"\u003e\n        \u003cimg src=\"https://github.com/stefanodvx/crunpyroll/assets/69367859/255bd391-3a7c-44f1-bf8c-08de275e73e9\" alt=\"Crunpyroll\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n#### Features 🔥\n- Fully async ([httpx](https://www.python-httpx.org/))\n- Python 3.7+ support\n- Clean and modern code\n- Updated to latest Crunchyroll API\n\n---\n\n#### Installation ⚙️\n```bash\n# Using Git\npip install -U git+https://github.com/stefanodvx/crunpyroll\n\n# Using PyPi (Recommended)\npip install -U crunpyroll\n```\n\n---\n\n#### Documentation 📄\nThe documentation page undergoes automatic updates with each push. To access the latest documentation page, kindly refer to our [Read the Docs](https://crunpyroll.readthedocs.io/) project.\n\n---\n\n#### Example Code ❓\n```py3\nimport crunpyroll\nimport asyncio\n\nclient = crunpyroll.Client(\n    email=\"email\",\n    password=\"password\",\n    locale=\"it-IT\"\n)\nasync def main():\n    # Start client and login\n    await client.start()\n    # Search for Attack on Titan\n    query = await client.search(\"Attack On Titan\")\n    series_id = query.items[0].id\n    print(series_id)\n    # Retrieve all seasons of the series\n    seasons = await client.get_seasons(series_id)\n    print(seasons)\n\nasyncio.run(main())\n```\n\n---\n\n#### Downloading content 🔑\nCrunchyroll has recently implemented the Widevine and PlayReady **Digital Rights Management (DRM)** systems, which has led to challenges for certain users attempting to download content from the platform.\n\nSubsequently, the following code provides an illustrative example of obtaining decryption keys through the utilities of the [pywidevine](https://github.com/devine-dl/pywidevine) library and an L3 Content Decryption Module (CDM).\n```py3\nfrom pywidevine.cdm import Cdm\nfrom pywidevine.pssh import PSSH\nfrom pywidevine.device import Device\n...\ndevice = Device.load(\"l3cdm.wvd\")\ncdm = Cdm.from_device(device)\n# Get streams of the episode/movie\nstreams = await client.get_streams(\"GRVDQ1G4R\")\n# Get manifest of the format you prefer\nmanifest = await client.get_manifest(streams.hardsubs[0].url)\n# print(manifest)\n# Get Widevine PSSH from manifest\npssh = PSSH(manifest.content_protection.widevine.pssh)\nsession_id = cdm.open()\nchallenge = cdm.get_license_challenge(session_id, pssh)\nlicense = await client.get_license(\n    streams.media_id,\n    challenge=challenge,\n    token=streams.token\n)\ncdm.parse_license(session_id, license)\nfor key in cdm.get_keys(session_id, \"CONTENT\"):\n    print(f\"{key.kid.hex}:{key.key.hex()}\")\ncdm.close(session_id)\n# Deleting active streams will prevent Crunchyroll HTTP 420 (too_many_queued_streams) error.\nawait client.delete_active_stream(\n    streams.media_id,\n    token=streams.token\n)\n```\nOutput:\n```bash\n056ec1ca849e350181753cacc9bd404b:2307a188ecd8de3859b71b30791f171d\n```\n\u003e [!TIP]\n\u003e Decryption keys are universally applicable to both video and audio streams, maintaining consistency across all available formats.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstefanodvx%2Fcrunpyroll","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstefanodvx%2Fcrunpyroll","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstefanodvx%2Fcrunpyroll/lists"}