v0.6.9
[0.6.9] - 2026-06-29
Added
- Proxy bypass list (
BROWSER_PROXY_BYPASS_LIST)
Route chosen domains around the proxy in the browser engine. The user-supplied list is passed to Chrome's--proxy-bypass-list
launch flag, so requests to those domains connect to the origin directly instead of through the proxy relay. Supports the full Chrome
bypass syntax — bare hostnames, wildcards (*.example.com), IP/CIDR ranges, ports, and the<local>token. Configured globally via
config/settings; only takes effect when a proxy is in use.
Fixed
-
Browser engine — pending tasks destroyed on ban-triggered restart
When one Scrapy thread triggered a browser restart after consecutive bans,
other concurrent_run_fetchcoroutines and their_smart_waitsleep()
children were left running on the old event loop and destroyed during
teardown. Restarts now block new fetches behind a restart barrier, drain
all pending loop tasks before stopping Chrome, and retry transient
connection errors once on the fresh browser. -
Browser engine — wrong-tab /
cannot call get() concurrently
Replacedbrowser.get(url, new_tab=True)with directcdp.target.create_target(url)to
guarantee a 1:1 mapping between the created CDP target and the Tab object, eliminating the
wrong-tab race and the duplicate_listener_taskthat caused the concurrency assertion. -
Browser engine —
_do_fetchtasks leaked on timeout
Tasks continued running afterfuture.result(timeout=...)raisedTimeoutError, holding
_tab_semslots and producing "Task was destroyed but it is pending!" on teardown.
The task is now cancelled directly vialoop.call_soon_threadsafe(task.cancel)on timeout. -
Browser engine —
"Event loop is closed"log noise
_chain_futurecallbacks andcall_soon_threadsafehandles firing against a closed loop
after_reset_browserare now suppressed by a teardown filter on theasyncioand
concurrent.futuresloggers. -
Browser engine —
AttributeError: 'NoneType' object has no attribute 'get'
Snapshottingbrowser = self._browserat_do_fetchentry prevents_reset_browser
nullingself._browsermid-execution from reachingbrowser.get(). -
Browser engine — Akamai 403 consuming full 30 s timeout
_wait_for_statusnow fast-exits on error page titles (Access Denied, Forbidden, etc.)
returning 403 immediately._smart_waitexits early when body length stops growing for 3 s. -
Browser engine —
logo.pngsplash causing wrong-tab on startup
_splash_url()now returns"about:blank"instead of afile://URI. -
Proxy relay — orphaned
handle()tasks on restart / shutdown
ProxyRelay.await_closed()now cancels and awaits all livehandle()tasks before
closing the server, replacing the bareserver.close()that left tasks running. -
Windows Proactor —
InvalidStateErrorcrashing the browser loop thread
_run_loopwrapsloop.run_forever()intry/except asyncio.InvalidStateError;
the loop exception handler suppresses it as well. -
Windows browser-restart log noise (
WinError 995)
Suppressed benign Windows Proactor teardown errors logged when the event loop and proxy relay are torn down during a browser restart.
The loop exception handler now ignoresWinError 995(ERROR_OPERATION_ABORTED) andWinError 64(ERROR_NETNAME_DELETED)
alongside the existing10054(WSAECONNRESET); genuine errors are still surfaced. The restart itself was always succeeding — only
the spuriousERRORtracebacks are gone. -
Temp profiles —
uc_*dirs accumulating in%TEMP%
_cleanup_browser_profiles()removes stale nodriver temp dirs on every restart and shutdown.
Changed
- Console — timestamp now styled
Fore.YELLOWto match Scrapy's log format.