Repository navigation
Stop on a refused proxy before starting a browser, and skip media behind a proxy - #6
Merged
Merged
Conversation
…ind a proxy The three browser engines send one HEAD for www.instagram.com/robots.txt through the first exit before launching a local browser; a gateway 407 or 402 ends the run with exit 5 and stop_reason proxy_auth_failed in <out>.latest_attempt.meta.json, leaving <out> and <out>.meta.json alone. Behind a local proxy they abort images, video/audio and web fonts (--load-media opts out); pyppeteer does it inside the Fetch handler that already answers the proxy's password prompt. Nothing changes over --cdp-endpoint, with --scraper-api or with no proxy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CKsd7q25N19WzUZjrAdzx8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A run through a paid residential proxy could start a browser per URL on a proxy that refuses every request (a gateway
407or402). The canary's own hint said such a407"reaches Chromium as a navigation timeout". Once a browser was running behind the proxy, it also downloaded every image, video and web font through the metered proxy, although every value is read from the JSON the page embeds.What changes
Proxy pre-check (all three browser engines). Before launching a local browser behind
--proxy/--proxy-file,playwright_scraper.py,puppeteer_scraper.pyandselenium_scraper.pysend ONEHEAD https://www.instagram.com/robots.txtthrough the exit the first URL would use. This isProxyPool.peek(), which does not move the rotation cursor. The shared logic is inpage_flow.proxy_precheck, and the helpers are inproxy_pool.py.407: exit 5, with the messagethe gateway refused the credential (or the traffic balance is exhausted).402: exit 5, with the messageproxy traffic/balance exhausted.INSTAGRAM_PROXYand never prints its value. The newoutput_writer.write_failed_attemptwrites only<out>.latest_attempt.meta.json(status: failed,stop_reason: proxy_auth_failed,data_updated: false), and<out>and<out>.meta.jsonare left as they were.--cdp-endpoint, with--scraper-api(no local proxy on that path) or with no proxy.Proxy.url()rebuilds the URL with percent-encoded credentials, for the HTTP client only.Media blocking. With a local browser behind a proxy, images, media and fonts are aborted:
context.routebyresource_type, on the per-URL context. The async API needs an awaited handler (_async_media_route), because the shared syncplaywright_media_routewould create the abort/continue coroutines and drop them unawaited.Fetchto answer the proxy's password prompt (Fetch.enablewithhandleAuthRequests). Its existingrequestPausedhandler now callsFetch.failRequest(BlockedByClient) forImage/Media/Font, so no second interception is opened. Without a password,proxy_pool.pyppeteer_block_mediapauses only those three resource types.Network.setBlockedURLsby file extension, right after the driver is built, so an image served without an extension still loads. If the CDP command fails, the engine warns and loads the media.--load-mediaopts out. A hidden--force-block-mediaturns blocking on without a proxy, for measurement.--scraper-apior with no proxy.<out>.meta.jsonrecordsmedia_blocked.env_config.ENV_KEYSmaps only credentials and URLs.The canary's
::error::hint for exit 5 now points at the pre-check.Evidence
Offline suite,
python3 smoke_test.py: 79/79 in a core-only venv, and 79/79 in each of the playwright, pyppeteer and selenium venvs. The engine-import assertion fromtests.ymlpasses in each venv.unittest discover,ci_checks.py(credential scan),ci_checks.py --sample-checkand every engine's--helpare green.New checks:
run()against a local stub proxy that answers every request, CONNECT included, with407or402. Each exits 5 after exactly oneCONNECT www.instagram.com:443, and the patched browser launch is never reached. The message names the variable and does not print the credential. The attempt sidecar reads failed/proxy_auth_failed with the rightengine. Earliero.json/o.json.meta.jsonkeep their bytes, and nothing else is written.403, the browser does start. A proxy that cannot be reached is not treated as a failure.--cdp-endpoint, with--scraper-apior with no proxy. The probe is the first URL'srobots.txtthrough the first exit, andpeek()does not consume the exit.--load-mediashown in--helpwhile--force-block-mediais hidden.--load-media, not over CDP).Fetch.enable, images/fonts/media failed and documents/scripts continued, nothing failed with--load-media, the resource-type-only path without a password, and noFetchopened when neither applies.media_blockedin the sidecar, and a source check per engine.The real CLIs against the stub proxy (
--proxy http://user:…@127.0.0.1:<stub>): Playwright, pyppeteer and Selenium each gave rc=5 for both 407 and 402. The stub saw one CONNECT, the secret did not appear in the output, and onlyo.json.latest_attempt.meta.jsonwas written.The real engine classes were driven through a local forwarding proxy, with Basic auth where the engine supports it, to a page containing png/jpg/woff2/mp4/js:
--load-media/and/app.jsreached the proxy, and the JS ranFetchhandler/,/app.jsand the browser's own/favicon.ico/,/app.jsand/favicon.ico/and/app.jsLive comparison on 2026-10-20, Playwright, no proxy,
--url natgeo, with and without--force-block-media: not possible. Both runs got Instagram's login page (exit 3), the datacentre behaviour already noted in the README. Instead, the parser was read for anything that depends on loaded media. Every field, image and video URLs included, comes from the embedded JSON blocks, and nothing reads image bytes or load state.Planted-fault controls, each restored afterwards and green again:
page_flow.proxy_precheckturns the three pre-check checks red.selenium_scraper.runturns three checks red, among themselenium_scraper 407: a browser was started._async_media_routecontinue everything turns the Playwright media check red. So does not installing the route.failRequestbranch turns the Puppeteer check red.selenium_block_media(driver)turns the Selenium check and the source check red.No paid calls, no proxy and no credentials were used.
Not changed
--scraper-api,scraper_api_engine.py) uses no local proxy, so it has no pre-check and no media blocking.🤖 Generated with Claude Code
https://claude.ai/code/session_01CKsd7q25N19WzUZjrAdzx8