Skip to content

Commit bfd28fc

Browse files
committed
cloud_browser: add solve_captcha kwarg to BrowserConfig + cloud_browser_unblock
Arms Scrapium's built-in captcha detector and solver on the first page attach. Turnstile, DataDome slider, reCAPTCHA, GeeTest, PerimeterX hold, and puzzle captchas are handled automatically — no extra CDP calls from the client. Billed per solve; failures cost nothing. BrowserConfig wires it through __init__, websocket_url (appends solve_captcha=true to the query string), to_dict, and from_dict. cloud_browser_unblock sends solve_captcha at the top level of the JSON body so the post-unblock session arms Antibot on connect.
1 parent 0887f52 commit bfd28fc

2 files changed

Lines changed: 16 additions & 0 deletions

File tree

scrapfly/browser_config.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ def __init__(
4444
browser_brand: Optional[str] = None,
4545
byop_proxy: Optional[str] = None,
4646
enable_mcp: Optional[bool] = None,
47+
solve_captcha: Optional[bool] = None,
4748
):
4849
if timeout is not None and timeout > 1800:
4950
raise ValueError('timeout cannot exceed 1800 seconds (30 minutes)')
@@ -83,6 +84,12 @@ def __init__(
8384
# https://scrapfly.io/docs/cloud-browser-api/byop
8485
self.byop_proxy = byop_proxy
8586
self.enable_mcp = enable_mcp
87+
# SolveCaptcha: arm Scrapium's built-in captcha detector + solver on
88+
# the first page attach. Turnstile, DataDome slider, reCAPTCHA,
89+
# GeeTest, PerimeterX hold, and puzzle captchas are handled
90+
# automatically. Billed per solve; failures cost nothing.
91+
# https://scrapfly.io/docs/cloud-browser-api/captcha-solver
92+
self.solve_captcha = solve_captcha
8693

8794
def websocket_url(self, api_key: str, host: Optional[str] = None) -> str:
8895
params = {'api_key': api_key}
@@ -153,6 +160,9 @@ def websocket_url(self, api_key: str, host: Optional[str] = None) -> str:
153160
if self.enable_mcp is not None:
154161
params['enable_mcp'] = self._bool_to_http(self.enable_mcp)
155162

163+
if self.solve_captcha is not None:
164+
params['solve_captcha'] = self._bool_to_http(self.solve_captcha)
165+
156166
base_host = host or self.CLOUD_BROWSER_HOST
157167
return base_host + '?' + urlencode(params)
158168

@@ -180,6 +190,7 @@ def to_dict(self) -> Dict:
180190
'browser_brand': self.browser_brand,
181191
'byop_proxy': self.byop_proxy,
182192
'enable_mcp': self.enable_mcp,
193+
'solve_captcha': self.solve_captcha,
183194
}
184195

185196
@staticmethod
@@ -215,4 +226,5 @@ def from_dict(browser_config_dict: Dict) -> 'BrowserConfig':
215226
browser_brand=browser_config_dict.get('browser_brand', None),
216227
byop_proxy=browser_config_dict.get('byop_proxy', None),
217228
enable_mcp=browser_config_dict.get('enable_mcp', None),
229+
solve_captcha=browser_config_dict.get('solve_captcha', None),
218230
)

scrapfly/client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,6 +1631,7 @@ def cloud_browser_unblock(
16311631
body: Optional[str] = None,
16321632
method: Optional[str] = None,
16331633
enable_mcp: Optional[bool] = None,
1634+
solve_captcha: Optional[bool] = None,
16341635
) -> Dict:
16351636
"""
16361637
Bypass anti-bot protection and get a ready-to-use browser session.
@@ -1679,6 +1680,9 @@ def cloud_browser_unblock(
16791680
if enable_mcp is not None:
16801681
json_body['enable_mcp'] = enable_mcp
16811682

1683+
if solve_captcha is not None:
1684+
json_body['solve_captcha'] = solve_captcha
1685+
16821686
response = self._http_handler(
16831687
method='POST',
16841688
url=self.cloud_browser_api_host + '/unblock',

0 commit comments

Comments
 (0)