Since some recent HowLongToBeat.com update, async_search() silently returns None
for every query (no exception raised) — confirmed this isn't an IP-block issue by
proxying requests through a separate server with normal browser headers; the site
loads fine and returns real content.
The site now appears to bundle its JS via Turbopack (Next.js), splitting code into
many chunk files with unpredictable hashed names
(e.g. /_next/static/chunks/1knrxcebl5umx.js, /_next/static/chunks/turbopack-3c7ykt0_ogp3s.js, etc.)
instead of a single predictable script location. The homepage HTML itself no longer
contains an inline fetch("/api/...", {method: "POST"...}) pattern that
SearchInformations.__extract_search_url_script (in HTMLRequests.py) can match,
so the search endpoint discovery fails and everything downstream returns None.
Reproduced on version 1.0.22 (latest on PyPI as of this report).
Steps to reproduce:
import asyncio
from howlongtobeatpy import HowLongToBeat
print(asyncio.run(HowLongToBeat().async_search("Assassin's Creed Odyssey")))
# -> None
Happy to help test a fix if useful.
Since some recent HowLongToBeat.com update,
async_search()silently returnsNonefor every query (no exception raised) — confirmed this isn't an IP-block issue by
proxying requests through a separate server with normal browser headers; the site
loads fine and returns real content.
The site now appears to bundle its JS via Turbopack (Next.js), splitting code into
many chunk files with unpredictable hashed names
(e.g.
/_next/static/chunks/1knrxcebl5umx.js,/_next/static/chunks/turbopack-3c7ykt0_ogp3s.js, etc.)instead of a single predictable script location. The homepage HTML itself no longer
contains an inline
fetch("/api/...", {method: "POST"...})pattern thatSearchInformations.__extract_search_url_script(in HTMLRequests.py) can match,so the search endpoint discovery fails and everything downstream returns None.
Reproduced on version 1.0.22 (latest on PyPI as of this report).
Steps to reproduce:
import asyncio
from howlongtobeatpy import HowLongToBeat
print(asyncio.run(HowLongToBeat().async_search("Assassin's Creed Odyssey")))
# -> None
Happy to help test a fix if useful.