1111import secrets
1212import uuid
1313from contextlib import contextmanager
14- from typing import Dict , Generator , Optional , Tuple
14+ from typing import Any , Dict , Generator , List , Optional , Tuple , Union
1515from urllib .parse import urlparse
1616
1717import boto3
2222from bedrock_agentcore ._utils .user_agent import build_user_agent_suffix
2323
2424from .._utils .endpoints import get_control_plane_endpoint , get_data_plane_endpoint
25+ from .config import BrowserExtension , ProfileConfiguration , ProxyConfiguration , ViewportConfiguration
26+
27+
28+ def _to_dict (value ):
29+ """Convert a dataclass or dict to a dict. Passes dicts through unchanged."""
30+ return value .to_dict () if hasattr (value , "to_dict" ) else value
31+
2532
2633DEFAULT_IDENTIFIER = "aws.browser.v1"
2734DEFAULT_SESSION_TIMEOUT = 3600
@@ -288,7 +295,10 @@ def start(
288295 identifier : Optional [str ] = DEFAULT_IDENTIFIER ,
289296 name : Optional [str ] = None ,
290297 session_timeout_seconds : Optional [int ] = DEFAULT_SESSION_TIMEOUT ,
291- viewport : Optional [Dict [str , int ]] = None ,
298+ viewport : Optional [Union [ViewportConfiguration , Dict [str , int ]]] = None ,
299+ proxy_configuration : Optional [Union [ProxyConfiguration , Dict [str , Any ]]] = None ,
300+ extensions : Optional [List [Union [BrowserExtension , Dict [str , Any ]]]] = None ,
301+ profile_configuration : Optional [Union [ProfileConfiguration , Dict [str , Any ]]] = None ,
292302 ) -> str :
293303 """Start a browser sandbox session.
294304
@@ -300,8 +310,20 @@ def start(
300310 name (Optional[str]): A name for this session.
301311 session_timeout_seconds (Optional[int]): The timeout for the session in seconds.
302312 Range: 1-28800 (8 hours). Default: 3600 (1 hour).
303- viewport (Optional[Dict[str, int]]): The viewport dimensions:
313+ viewport (Optional[Union[ViewportConfiguration, Dict[str, int]]]): The viewport
314+ dimensions. Can be a ViewportConfiguration dataclass or a plain dict:
304315 {'width': 1920, 'height': 1080}
316+ proxy_configuration (Optional[Union[ProxyConfiguration, Dict[str, Any]]]): Proxy
317+ configuration for routing browser traffic through external proxy servers.
318+ Can be a ProxyConfiguration dataclass or a plain dict matching the API shape.
319+ extensions (Optional[List[Union[BrowserExtension, Dict[str, Any]]]]): List of
320+ browser extensions to load into the session. Each element can be a
321+ BrowserExtension dataclass or a plain dict:
322+ [{"location": {"s3": {"bucket": "...", "prefix": "..."}}}]
323+ profile_configuration (Optional[Union[ProfileConfiguration, Dict[str, Any]]]): Profile
324+ configuration for persisting browser state across sessions. Can be a
325+ ProfileConfiguration dataclass or a plain dict:
326+ {"profileIdentifier": "my-profile-id"}
305327
306328 Returns:
307329 str: The session ID of the newly created session.
@@ -316,6 +338,20 @@ def start(
316338 ... viewport={'width': 1920, 'height': 1080},
317339 ... session_timeout_seconds=7200 # 2 hours
318340 ... )
341+ >>>
342+ >>> # Use proxy configuration
343+ >>> session_id = client.start(
344+ ... proxy_configuration={
345+ ... "proxies": [{
346+ ... "externalProxy": {
347+ ... "server": "proxy.example.com",
348+ ... "port": 8080,
349+ ... "domainPatterns": [".example.com"],
350+ ... }
351+ ... }],
352+ ... "bypass": {"domainPatterns": [".amazonaws.com"]}
353+ ... }
354+ ... )
319355 """
320356 self .logger .info ("Starting browser session..." )
321357
@@ -326,7 +362,16 @@ def start(
326362 }
327363
328364 if viewport is not None :
329- request_params ["viewPort" ] = viewport
365+ request_params ["viewPort" ] = _to_dict (viewport )
366+
367+ if proxy_configuration is not None :
368+ request_params ["proxyConfiguration" ] = _to_dict (proxy_configuration )
369+
370+ if extensions is not None :
371+ request_params ["extensions" ] = [_to_dict (e ) for e in extensions ]
372+
373+ if profile_configuration is not None :
374+ request_params ["profileConfiguration" ] = _to_dict (profile_configuration )
330375
331376 response = self .data_plane_client .start_browser_session (** request_params )
332377
@@ -581,14 +626,26 @@ def release_control(self):
581626
582627@contextmanager
583628def browser_session (
584- region : str , viewport : Optional [Dict [str , int ]] = None , identifier : Optional [str ] = None
629+ region : str ,
630+ viewport : Optional [Union [ViewportConfiguration , Dict [str , int ]]] = None ,
631+ identifier : Optional [str ] = None ,
632+ proxy_configuration : Optional [Union [ProxyConfiguration , Dict [str , Any ]]] = None ,
633+ extensions : Optional [List [Union [BrowserExtension , Dict [str , Any ]]]] = None ,
634+ profile_configuration : Optional [Union [ProfileConfiguration , Dict [str , Any ]]] = None ,
585635) -> Generator [BrowserClient , None , None ]:
586636 """Context manager for creating and managing a browser sandbox session.
587637
588638 Args:
589639 region (str): AWS region.
590- viewport (Optional[Dict[str, int]]): Viewport dimensions.
640+ viewport (Optional[Union[ViewportConfiguration, Dict[str, int]]]): Viewport dimensions.
641+ Can be a ViewportConfiguration dataclass or a plain dict.
591642 identifier (Optional[str]): Browser identifier (system or custom).
643+ proxy_configuration (Optional[Union[ProxyConfiguration, Dict[str, Any]]]): Proxy
644+ configuration. Can be a ProxyConfiguration dataclass or a plain dict.
645+ extensions (Optional[List[Union[BrowserExtension, Dict[str, Any]]]]): Browser
646+ extensions. Each element can be a BrowserExtension dataclass or a plain dict.
647+ profile_configuration (Optional[Union[ProfileConfiguration, Dict[str, Any]]]): Profile
648+ configuration. Can be a ProfileConfiguration dataclass or a plain dict.
592649
593650 Yields:
594651 BrowserClient: An initialized and started browser client.
@@ -602,13 +659,26 @@ def browser_session(
602659 >>> with browser_session('us-west-2', identifier='my-signed-browser') as client:
603660 ... # Automation with reduced CAPTCHA friction
604661 ... pass
662+ ...
663+ >>> # Use proxy configuration
664+ >>> with browser_session('us-west-2', proxy_configuration={
665+ ... "proxies": [{"externalProxy": {"server": "proxy.corp.com", "port": 8080}}],
666+ ... "bypass": {"domainPatterns": [".amazonaws.com"]}
667+ ... }) as client:
668+ ... ws_url, headers = client.generate_ws_headers()
605669 """
606670 client = BrowserClient (region )
607671 start_kwargs = {}
608672 if viewport is not None :
609673 start_kwargs ["viewport" ] = viewport
610674 if identifier is not None :
611675 start_kwargs ["identifier" ] = identifier
676+ if proxy_configuration is not None :
677+ start_kwargs ["proxy_configuration" ] = proxy_configuration
678+ if extensions is not None :
679+ start_kwargs ["extensions" ] = extensions
680+ if profile_configuration is not None :
681+ start_kwargs ["profile_configuration" ] = profile_configuration
612682
613683 client .start (** start_kwargs )
614684
0 commit comments