1

Get your API Key

Visit the Dashboardโ€™s Overview tab:

Then copy and set the BROWSERBASE_API_KEY and BROWSERBASE_PROJECT_ID environment variables in your .env file.

2

Install and create a virtual environment with UV

UV is a modern package manager for Python.

uv venv
3

Install Browserbase and Browser Use

source .venv/bin/activate # follow the `uv venv` output
uv pip install browserbase browser-use langchain-anthropic python-dotenv
4

Create the Managed Browser Session Class

Weโ€™ll create a session management class that handles proper browser lifecycle management following Browser Use best practices.

main.py
import asyncio
import os
from dotenv import load_dotenv

from browserbase import Browserbase
from browser_use import Agent
from browser_use.browser.session import BrowserSession
from browser_use.browser import BrowserProfile
from langchain_anthropic import ChatAnthropic


class ManagedBrowserSession:
    """Context manager for proper BrowserSession lifecycle management"""
    
    def __init__(self, cdp_url: str, browser_profile: BrowserProfile):
        self.cdp_url = cdp_url
        self.browser_profile = browser_profile
        self.browser_session = None
        
    async def __aenter__(self) -> BrowserSession:
        try:
            self.browser_session = BrowserSession(
                cdp_url=self.cdp_url,
                browser_profile=self.browser_profile,
                keep_alive=False,  # Essential for proper cleanup
                initialized=False,
            )
            
            await self.browser_session.start()
            print("โœ… Browser session initialized successfully")
            return self.browser_session
            
        except Exception as e:
            print(f"โŒ Failed to initialize browser session: {e}")
            await self._emergency_cleanup()
            raise
    
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        await self._close_session_properly()
    
    async def _close_session_properly(self):
        playwright_instance = None
        
        try:
            if self.browser_session:
                # Get playwright instance before closing session
                if hasattr(self.browser_session, 'playwright'):
                    playwright_instance = self.browser_session.playwright
                
                # Close browser session first
                if self.browser_session.initialized:
                    await self.browser_session.stop()
                    print("โœ… Browser session closed successfully")
                    
        except Exception as e:
            error_msg = str(e).lower()
            if "browser is closed" in error_msg or "disconnected" in error_msg:
                print("โ„น๏ธ  Browser session was already closed (expected behavior)")
            else:
                print(f"โš ๏ธ  Error during browser session closure: {e}")
        
        finally:
            # Stop playwright instance - critical for preventing hanging processes
            if playwright_instance:
                try:
                    await playwright_instance.stop()
                    print("โœ… Playwright instance stopped successfully")
                except Exception as e:
                    print(f"โš ๏ธ  Error stopping Playwright: {e}")
            
            await self._final_cleanup()
    
    async def _emergency_cleanup(self):
        try:
            if self.browser_session:
                if hasattr(self.browser_session, 'playwright'):
                    await self.browser_session.playwright.stop()
                if self.browser_session.initialized:
                    await self.browser_session.stop()
        except Exception as e:
            print(f"โš ๏ธ  Emergency cleanup error: {e}")
        finally:
            await self._final_cleanup()
    
    async def _final_cleanup(self):
        self.browser_session = None
5

Create Helper Functions

Add helper functions for creating Browserbase sessions and configuring browser profiles:

main.py
async def create_browserbase_session():
    load_dotenv()
    
    bb = Browserbase(api_key=os.environ["BROWSERBASE_API_KEY"])
    session = bb.sessions.create(project_id=os.environ["BROWSERBASE_PROJECT_ID"])
    
    print(f"Session ID: {session.id}")
    print(f"Debug URL: https://www.browserbase.com/sessions/{session.id}")
    
    return session


def create_browser_profile() -> BrowserProfile:
    return BrowserProfile(
        keep_alive=False,  # Essential for proper cleanup
        wait_between_actions=2.0,
        default_timeout=30000,
        default_navigation_timeout=30000,
    )


async def run_automation_task(browser_session: BrowserSession, task: str) -> str:
    llm = ChatAnthropic(model="claude-3-5-sonnet-20240620", temperature=0.0)
    
    agent = Agent(
        task=task,
        llm=llm,
        browser_session=browser_session,
        enable_memory=False,
        max_failures=5,
        retry_delay=5,
        max_actions_per_step=1,
    )
    
    try:
        print("๐Ÿš€ Starting agent task...")
        result = await agent.run(max_steps=20)
        print("๐ŸŽ‰ Task completed successfully!")
        return str(result)
        
    except Exception as e:
        # Handle expected browser disconnection after successful completion
        error_msg = str(e).lower()
        if "browser is closed" in error_msg or "disconnected" in error_msg:
            print("โœ… Task completed - Browser session ended normally")
            return "Task completed successfully (session ended normally)"
        else:
            print(f"โŒ Agent execution error: {e}")
            raise
            
    finally:
        del agent
6

Create the Main Function

Implement the main execution function with comprehensive error handling:

main.py
async def main():
    try:
        session = await create_browserbase_session()
        browser_profile = create_browser_profile()
        
        task = ("Go to https://www.macrumors.com/contact.php and fill in the form. "
                "Make sure to use the selectors and submit the form")
        
        async with ManagedBrowserSession(session.connect_url, browser_profile) as browser_session:
            result = await run_automation_task(browser_session, task)
            print(f"Final result: {result}")
            
    except KeyboardInterrupt:
        print("\nโน๏ธ  Process interrupted by user")
    except Exception as e:
        print(f"๐Ÿ’ฅ Fatal error: {e}")
        raise
    finally:
        print("๐Ÿ Application shutdown complete")


if __name__ == "__main__":
    asyncio.run(main())
7

Run your script

Run your script:

uv run main.py

You should see your Browserbase session start in Browserbase. The debug URL will be printed to console for real-time session monitoring.

Important Environment Variables

Make sure you have these environment variables in your .env file:

  • BROWSERBASE_API_KEY
  • BROWSERBASE_PROJECT_ID
  • ANTHROPIC_API_KEY

Key Features of This Implementation

  • Clean Resource Management: Context manager ensures proper cleanup without complexity
  • Essential Error Handling: Handles browser disconnections and cleanup failures gracefully
  • Simplified Approach: Focused on core functionality without unnecessary overhead
  • Production Ready: Robust enough for real-world applications

Browser Use Best Practices Implemented

  • Set keep_alive=False for proper session cleanup
  • Use reasonable timeouts to prevent hanging processes
  • Implement proper Playwright instance cleanup
  • Handle expected browser disconnections after task completion
  • Use structured error handling with clear logging

Common Issues & Fixes

  • Browser disconnection after successful form submission is expected behavior
  • The context manager ensures proper cleanup even if errors occur
  • Playwright instance cleanup prevents hanging processes
  • Emergency cleanup handles initialization failures gracefully
  • Reach out to us at support@browserbase.com for additional support