@@ -35,6 +35,7 @@ def __init__(
3535 storage_state : str | Path | StorageState | dict | None = None ,
3636 record_video_dir : str | Path | None = None ,
3737 record_video_size : dict [str , int ] | None = None ,
38+ viewport : dict [str , int ] | None = None ,
3839 ):
3940 """
4041 Initialize Sentience browser
@@ -67,6 +68,11 @@ def __init__(
6768 Examples: {"width": 1280, "height": 800} (default)
6869 {"width": 1920, "height": 1080} (1080p)
6970 If None, defaults to 1280x800.
71+ viewport: Optional viewport size as dict with 'width' and 'height' keys.
72+ Examples: {"width": 1280, "height": 800} (default)
73+ {"width": 1920, "height": 1080} (Full HD)
74+ {"width": 375, "height": 667} (iPhone)
75+ If None, defaults to 1280x800.
7076 """
7177 self .api_key = api_key
7278 # Only set api_url if api_key is provided, otherwise None (free tier)
@@ -94,6 +100,9 @@ def __init__(
94100 self .record_video_dir = record_video_dir
95101 self .record_video_size = record_video_size or {"width" : 1280 , "height" : 800 }
96102
103+ # Viewport configuration
104+ self .viewport = viewport or {"width" : 1280 , "height" : 800 }
105+
97106 self .playwright : Playwright | None = None
98107 self .context : BrowserContext | None = None
99108 self .page : Page | None = None
@@ -211,7 +220,7 @@ def start(self) -> None:
211220 "user_data_dir" : user_data_dir ,
212221 "headless" : False , # IMPORTANT: See note above
213222 "args" : args ,
214- "viewport" : { "width" : 1280 , "height" : 800 } ,
223+ "viewport" : self . viewport ,
215224 # Remove "HeadlessChrome" from User Agent automatically
216225 "user_agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" ,
217226 }
@@ -480,6 +489,97 @@ def close(self, output_path: str | Path | None = None) -> str | None:
480489
481490 return final_path
482491
492+ @classmethod
493+ def from_existing (
494+ cls ,
495+ context : BrowserContext ,
496+ api_key : str | None = None ,
497+ api_url : str | None = None ,
498+ ) -> "SentienceBrowser" :
499+ """
500+ Create SentienceBrowser from an existing Playwright BrowserContext.
501+
502+ This allows you to use Sentience SDK with a browser context you've already created,
503+ giving you more control over browser initialization.
504+
505+ Args:
506+ context: Existing Playwright BrowserContext
507+ api_key: Optional API key for server-side processing
508+ api_url: Optional API URL (defaults to https://api.sentienceapi.com if api_key provided)
509+
510+ Returns:
511+ SentienceBrowser instance configured to use the existing context
512+
513+ Example:
514+ from playwright.sync_api import sync_playwright
515+ from sentience import SentienceBrowser, snapshot
516+
517+ with sync_playwright() as p:
518+ context = p.chromium.launch_persistent_context(...)
519+ browser = SentienceBrowser.from_existing(context)
520+ browser.page.goto("https://example.com")
521+ snap = snapshot(browser)
522+ """
523+ instance = cls (api_key = api_key , api_url = api_url )
524+ instance .context = context
525+ instance .page = context .pages [0 ] if context .pages else context .new_page ()
526+
527+ # Apply stealth if available
528+ if STEALTH_AVAILABLE :
529+ stealth_sync (instance .page )
530+
531+ # Wait for extension to be ready (if extension is loaded)
532+ time .sleep (0.5 )
533+
534+ return instance
535+
536+ @classmethod
537+ def from_page (
538+ cls ,
539+ page : Page ,
540+ api_key : str | None = None ,
541+ api_url : str | None = None ,
542+ ) -> "SentienceBrowser" :
543+ """
544+ Create SentienceBrowser from an existing Playwright Page.
545+
546+ This allows you to use Sentience SDK with a page you've already created,
547+ giving you more control over browser initialization.
548+
549+ Args:
550+ page: Existing Playwright Page
551+ api_key: Optional API key for server-side processing
552+ api_url: Optional API URL (defaults to https://api.sentienceapi.com if api_key provided)
553+
554+ Returns:
555+ SentienceBrowser instance configured to use the existing page
556+
557+ Example:
558+ from playwright.sync_api import sync_playwright
559+ from sentience import SentienceBrowser, snapshot
560+
561+ with sync_playwright() as p:
562+ browser_instance = p.chromium.launch()
563+ context = browser_instance.new_context()
564+ page = context.new_page()
565+ page.goto("https://example.com")
566+
567+ browser = SentienceBrowser.from_page(page)
568+ snap = snapshot(browser)
569+ """
570+ instance = cls (api_key = api_key , api_url = api_url )
571+ instance .page = page
572+ instance .context = page .context
573+
574+ # Apply stealth if available
575+ if STEALTH_AVAILABLE :
576+ stealth_sync (instance .page )
577+
578+ # Wait for extension to be ready (if extension is loaded)
579+ time .sleep (0.5 )
580+
581+ return instance
582+
483583 def __enter__ (self ):
484584 """Context manager entry"""
485585 self .start ()
0 commit comments