Browser Use: Practical Examples

Code examples that show practical uses of Browser Use.
By Boris Delovski • Updated on Jun 2, 2025
blog image

In the previous article in this series, we introduced Browser Use. It’s a tool that enables LLMs to interact with the Internet in human-like ways, such as booking appointments, buying products from websites, and more. That article focused on explaining how Browser Use operates behind the scenes. This article will take a more practical approach. We will provide concrete code examples to show how you can effectively use Browser Use to interact with webpages through an LLM.

We will cover several examples demonstrating how to use Browser Use, starting with basic scenarios. From there, we will gradually move on to more advanced use cases. Additionally, we will explain how to integrate Browser Use with both cloud-based and locally deployed LLMs. By the end of this article, you will have the essential knowledge required to start working with Browser Use effectively.

Article continues below

Browser Use Example: How Can You Collect Headline Titles Using a Cloud LLM

Let’s demonstrate how to use Browser Use to navigate the BBC news website and print every headline on the page. At first glance, this might seem like a simple task, and compared to more advanced use cases, it is. However, it still requires more than what standard scraping tools can typically handle

For instance, the moment you enter the site, you are prompted to select which cookies to allow. Browser Use can handle this step gracefully, while most traditional systems struggle with it. Additionally, different webpage elements often change dynamically. This is another challenge that Browser Use can adapt to, unlike many basic scraping tools. 

So, even though this example appears basic, accomplishing the same result with conventional tools would require quite a bit of code. As you will see soon, Browser Use allows us to achieve this with just a few lines of code.

The Agent class will always remain the most important part of the code. This class serves as the core component responsible for handling browser automation. It requires only two mandatory arguments:

  • task
  • llm

The task argument defines the instruction we want the agent to execute. In our example, the task will be: "Open the BBC News homepage and list all headline titles."

The llm argument refers to an instance of a LangChain chat model. Browser Use supports a diverse range of models, including both cloud-hosted and locally deployable options. Among the most commonly used cloud-based models are:

  • OpenAI’s GPT models
  • Anthropic’s Claude models
  • Google’s Gemini models
  • DeepSeek’s V and R series of models

To access any of these models, Browser Use requires an API key. All API keys should be stored in an .env file. Below is an example of how the .env file would look if we planned to use the most popular models interchangeably:

OPENAI_API_KEY=<your API key here>
ANTHROPIC_API_KEY=<your API key here>
GEMINI_API_KEY=<your API key here>
DEEPSEEK_API_KEY=<your API key here>

Usually, to load API keys from the .env file, we use dotenv, a Python library that reads key-value pairs from a text file named .env and loads them into process-level environment variables. This allows your code to access them via os.getenv() or os.environ. By using dotenv, you can keep sensitive information like API keys, database URLs, and tokens out of your source code and version control. This method also enables you to configure your program locally, in CI/CD, and in production without requiring code changes.

Therefore, to define an Agent that, for example, uses Google Gemini to list headline titles from the BBC News webpage, we would first create an instance of the Agent class. This would look like the following:

import os
import asyncio
from dotenv import load_dotenv
from langchain_google_genai import ChatGoogleGenerativeAI
from browser_use import Agent

# --------------------------------------------------------------------------- #
# 1. Environment initialisation                                               #
# --------------------------------------------------------------------------- #

load_dotenv()  # Load key-value pairs from `.env` into `os.environ`

# Retrieve the Gemini API key; fail fast with a helpful hint if it’s missing
api_key = os.getenv("GEMINI_API_KEY")
if api_key is None:
    raise EnvironmentError(
        "GEMINI_API_KEY not found. Create a .env file with:\n"
        "GEMINI_API_KEY=your_key_here"
    )

# --------------------------------------------------------------------------- #
# 2. Large-Language-Model (LLM) setup                                         #
# --------------------------------------------------------------------------- #

LLM = ChatGoogleGenerativeAI(
    model="gemini-1.5-flash-latest",  # Gemini model with a free tier
    google_api_key=api_key,
)

# --------------------------------------------------------------------------- #
# 3. Main entry point                                                         #
# --------------------------------------------------------------------------- #
async def main():
    """
    Build a browser agent that navigates to BBC News and prints every headline.

    The `browser_use.Agent` class (imported above) is responsible for:
      • launching a browser
      • interpreting the natural-language *task* with help from the LLM
      • interacting with the DOM to locate headline elements
      • streaming the collected titles back to the console
    """
    task = "Open the BBC News homepage and list all headline titles."
    agent = Agent(task=task, llm=LLM)
    await agent.run()  # Run the agent and wait for it to finish

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

As you can see above, after loading the required API key with dotenv, and defining which LLM we want to use with LangChain, we followed up with two design patterns. These may seem unfamiliar to Python beginners, but in practice, they are integral parts of every Browser Use Python script:

  • We always wrap almost everything inside one main coroutine, called async def main():
  • We guard the call to that coroutine using  if __name__ == "__main__":

The guard’s purpose is simple: it ensures that the if __name__ == "__main__": condition only triggers when the file is executed as a script. It will not run if the file is imported as a module. This prevents unintended side effects (like opening a browser, starting an event loop, or making API calls) when another module simply wants to reuse your helper functions. It works because the Python interpreter sets the special variable __name__ to the string "__main__" only when the file is being run directly. If the same file is imported as a module,  __name__ will instead hold the module’s actual name (e.g., browser_use).

Now, let’s discuss coroutines. When you call an async def function, it doesn’t “run code”.  Instead, it returns a coroutine object, which is a lightweight handle that can be scheduled to run later by an event loop. You can think of this coroutine as a paused generator, which will only advance when the event loop decides it’s time for that particular task to run. If you try to execute the function directly, you’ll simply get this coroutine object. To run the code inside the function, you must either await it inside another coroutine or pass it to a helper like asyncio.run().

asyncio manages a single event loop that switches between multiple awaiting coroutines whenever one would otherwise be blocked, such as during I/O operations (network traffic, disk reads, timers, etc.). Since the loop never waits idly, you can write straight-line code that overlaps these waits, all without the need to create additional OS threads. This is the “non-blocking” advantage often referred to, allowing more efficient use of resources.

This approach is crucial for Browser Use. Agents in Browser Use perform a variety of operations, such as opening a browser, waiting for pages to load, and querying the DOM. Each of these tasks involves remote or GPU waits, rather than CPU crunching. By using await methods, the task yields control while the browser idles, allowing other coroutines (or cancellation signals) to run in the meantime. Today, asyncio.run() is commonly used to create such loops, a convenience wrapper introduced in Python 3.7.

In simple terms:

  • async def main() – defines work that might need to “pause” at certain points.
  • It creates coroutines for the work instead of running it immediately.
  • asyncio.run() – starts the event loop, runs the coroutines, and shuts everything down.

Most often, Browser Use will return results in the form of a JSON file. For example, the result from running the code above is:

{
  "headline_titles": [
    "Trump celebrates 100 days in office by touting record and blasting foes",
    "Border crossings, egg prices and jobs - Trump's 100 days speech fact-checked",
    "Life inside Iraq's 'Forbidden Zone' controlled by Turkey",
    "Pakistan claims 'credible intelligence' India is planning an imminent military strike",
    "Food authors say Australian influencer copied their recipes",
    "Border crossings, egg prices and jobs - Trump's 100 days speech fact-checked",
    "Toxic mushroom meal was 'terrible accident', says woman on trial for murder",
    "Swedish police arrest teenager after fatal triple shooting",
    "Trump congratulates Canada's Carney as they agree to meet in 'near future'",
    "Life inside Iraq's 'Forbidden Zone' controlled by Turkey",
    "Major Gianni Versace exhibition to open in London",
    "LIVE Watch: Top UN court hears case on Israel's obligation to ensure aid reaches Palestinians",
    "Harvard head apologises as scathing reports on campus prejudice released",
    "Starbucks to hire more baristas in bid to win back customers",
    "UK government defends net-zero policies after criticism from former PM Blair",
    "Trump's 100 days",
    "Trump eases car tariffs after firms raised concerns",
    "Trump calls Bezos as Amazon says no plan to show tariff price rises",
    "Your questions on tariffs, annexation and immigration after Trump's first 100 days",
    "How Trump's presidency compares to his predecessors",
    "Trump's breakneck start is fraught with political risk",
    "More to explore",
    "Xi's real test is not Trump's trade war",
    "Five things you need to make it through a power cut",
    "Fifty years after the war, Vietnam faces a new US threat - tariffs",
    "The TikTokers accused of triggering an election scandal",
    "Kneecap: Rap group are no strangers to controversy, but is this time different?",
    "Five things you need to make it through a power cut",
    "William and Kate visit Mull to celebrate wedding anniversary",
    "Australia's last vote was all about Indigenous people - now they say it's 'silence'",
    "Fifty years after the war, Vietnam faces a new US threat - tariffs",
    "Canada election",
    "Trump made Carney's turnaround victory possible",
    "How Canada voted - in charts",
    "'Build, baby, build': Five things Carney has pledged to do as Canadian PM",
    "Relief, disappointment or surprise? Canadians react to election result",
    "Carney's Liberals won. What happens next?",
    "Also in news",
    "Canada will deal with US 'on our terms', PM Carney tells BBC",
    "First UK strikes on Houthis in Yemen in 18 months",
    "Robot vacuums could be used to water plants or play with cats, UK scientists say",
    "PSG beat Arsenal to take advantage in Champions League semi-final",
    "Pressure mounts to probe Kenya police and army after BBC exposé",
    "First UK strikes on Houthis in Yemen in 18 months",
    "'He kept saying I'm a murderer': Polish doctor targeted for legal abortion",
    "Gaza medic detained during deadly Israeli attack released, Red Crescent says",
    "Robot vacuums could be used to water plants or play with cats, UK scientists say",
    "Most watched",
    "Fire destroys historic US church with ties to MLK",
    "Relief, disappointment or surprise? Canadians react to election result",
    "Watch: Disruption continues in Madrid as power resumes",
    "Watch: Crew survives after powerboat goes airborne and crashes",
    "Will Canada's newly-elected PM agree to meet Trump?",
    "Most read",
    "Border crossings, egg prices and jobs - Trump's 100 days speech fact-checked",
    "Swedish police arrest teenager after fatal triple shooting",
    "Trump celebrates 100 days in office by touting record and blasting foes",
    "Toxic mushroom meal was 'terrible accident', says woman on trial for murder",
    "Harvard head apologises as scathing reports on campus prejudice released",
    "Pakistan claims 'credible intelligence' India is planning an imminent military strike",
    "Xi's real test is not Trump's trade war",
    "Life inside Iraq's 'Forbidden Zone' controlled by Turkey",
    "Five things you need to make it through a power cut",
    "Trump calls Bezos as Amazon says no plan to show tariff price rises",
    "Sport",
    "PSG pass masters make Rice and Arsenal's fears come true",
    "LIVE Champions League: Reaction to Arsenal's semi-final first-leg defeat to PSG",
    "'Disrespectful' dad criticised as Pacers beat Bucks",
    "I don't compare myself to Messi - Barca star Yamal",
    "'Why hit a single when you can hit six?' - the making of a teen IPL star",
    "LIVE Champions League: Reaction to Arsenal's semi-final first-leg defeat to PSG",
    "McIlroy to play Scottish Open before Portrush bid",
    "An Inter legend conquering the world - how Martinez's dream came true",
    "'Disrespectful' dad criticised as Pacers beat Bucks"
  ]
}

Since the headlines change, the result you get when running the code may vary depending on the time of execution. However, the format should remain consistent.

Browser Use Example: How Can You Collect Headline Titles Using a Locally Deployed LLM

If you want to use a locally deployed LLM for the same task, the process becomes simpler. You won’t need to manage any API keys or other similar configurations. Instead, you can use Ollama in combination with LangChain to define your model. 

Ollama is a lightweight CLI tool and background service that allows you to run open-source LLMs entirely on your own machine. With Ollama, you can pull models from its available library and run them locally using LangChain (more specifically, the ChatOllama module from LangChain). For instance, let's modify the previous code so that, instead of using Google Gemini, we use Qwen 3-8B, a recent LLM from Alibaba Cloud’s open-source family.

Do note that, in most cases, results from locally deployed models typically won't match the performance of cloud-deployed models. This is mainly because most consumer hardware cannot handle large models effectively. Therefore, you are working with a much weaker LLM, which often leads to subpar results. However, there are two ways to improve performance:

  • Use more detailed prompts.
  • Use message contexts.

A more detailed prompt ensures that the LLM has a clearer understanding of the task at hand. Moreover, using message contexts allows us to provide separate guidelines for the LLM, helping it understand how to behave during the task. With these improvements, our final code will look like this:

import asyncio
from langchain_ollama import ChatOllama
from browser_use import Agent


# --------------------------------------------------------------------------- #
# 1. Large-Language-Model (LLM) setup                                         #
# --------------------------------------------------------------------------- #

# We pick **qwen3** and request a 32-k token context.
LLM = ChatOllama(
    model="qwen3:8b",
    num_ctx=32000  # Maximum context length in tokens
)

# --------------------------------------------------------------------------- #
# 2. Main entry point                                                         #
# --------------------------------------------------------------------------- #
async def main():
    """
    Build a browser agent that navigates to BBC News and prints every headline.

    The `browser_use.Agent` class (imported above) is responsible for:
      • launching a browser
      • interpreting the natural-language *task* with help from the LLM
      • interacting with the DOM to locate headline elements
      • streaming the collected titles back to the console
    """
    task = (
        "Open the BBC News homepage, collect all of the headline "
        "titles and return them to me in the form of a list. "
        "Do not try to input text into index, just return it back to me."
        
    )

    message_context = (
        "If a cookie-consent banner blocks the content, first click a button that"
        "dismisses it (e.g. “Accept”, “Allow all”, “OK”). Search for it using vision the vision model."
        "Then continue the task."
        "If a captcha appears, solve it using the vision model."
        "After circumventing cookie prompts and captchas, collect all of the headline titles."
    )

    agent = Agent(task=task, llm=LLM, use_vision=True, message_context=message_context)
    await agent.run()  # Run the agent and wait for it to finish

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

After running this code, the agent will return the following list of headline titles:

{
  "headlines": [
    "Trump celebrates 100 days in office by touting record and blasting foes",
    "Border crossings, egg prices and jobs - Trump's 100 days speech fact-checked",
    "Life inside Iraq's 'Forbidden Zone' controlled by Turkey",
    "Pakistan claims 'credible intelligence' India is planning an imminent military strike",
    "Food authors say Australian influencer copied their recipes",
    "Border crossings, egg prices and jobs - Trump's 100 days speech fact-checked",
    "Toxic mushroom meal was 'terrible accident', says woman on trial for murder",
    "Swedish police arrest teenager after fatal triple shooting",
    "Trump congratulates Canada's Carney as they agree to meet in 'near future'",
    "Life inside Iraq's 'Forbidden Zone' controlled by Turkey",
    "Major Gianni Versace exhibition to open in London",
    "Drone footage shows scale of deadly Peru landslide",
    "Israeli forces arrest prominent Palestinian journalist in West Bank",
    "LIVE: Top UN court hears case on Israel's obligation to ensure aid reaches Palestinians",
    "Starbucks to hire more baristas in bid to win back customers",
    "Trump's 100 days",
    "Trump eases car tariffs after firms raised concerns",
    "Trump calls Bezos as Amazon says no plan to show tariff price rises",
    "100 Days of Donald Trump",
    "Your questions on tariffs, annexation and immigration after Trump's first 100 days",
    "How Trump's presidency compares to his predecessors",
    "Xi's real test is not Trump's trade war",
    "Five things you need to make it through a power cut",
    "Fifty years after the war, Vietnam faces a new US threat - tariffs",
    "The TikTokers accused of triggering an election scandal",
    "Kneecap: Rap group are no strangers to controversy, but is this time different?",
    "Five things you need to make it through a power cut",
    "William and Kate visit Mull to celebrate wedding anniversary",
    "Australia's last vote was all about Indigenous people - now they say it's 'silence'",
    "Fifty years after the war, Vietnam faces a new US threat - tariffs",
    "Trump's 100 days",
    "Trump made Carney's turnaround victory possible",
    "How Canada voted - in charts",
    "'Build, baby, build': Five things Carney has pledged to do as Canadian PM",
    "Relief, disappointment or surprise? Canadians react to election result",
    "Carney's Liberals won. What happens next?",
    "More Kneecap gigs cancelled amid 'kill your MP' controversy",
    "Taiwan condemns Somalia travel ban",
    "UK government defends net-zero policies after criticism from former PM Blair",
    "First UK strikes on Houthis in Yemen in 18 months",
    "Robot vacuums could be used to water plants or play with cats, UK scientists say",
    "Taiwan condemns Somalia travel ban",
    "Watch: Trump jokes he'd 'like to be Pope'",
    "Harvard head apologises as scathing reports on campus prejudice released",
    "UK government defends net-zero policies after criticism from former PM Blair",
    "Most watched",
    "Watch: Trump jokes he'd 'like to be Pope'",
    "Fire destroys historic US church with ties to MLK",
    "Drone footage shows scale of deadly Peru landslide",
    "Relief, disappointment or surprise? Canadians react to election result",
    "Watch: Crew survives after powerboat goes airborne and crashes",
    "Most read",
    "Border crossings, egg prices and jobs - Trump's 100 days speech fact-checked",
    "Swedish police arrest teenager after fatal triple shooting",
    "Trump celebrates 100 days in office by touting record and blasting foes",
    "Toxic mushroom meal was 'terrible accident', says woman on trial for murder",
    "Pakistan claims 'credible intelligence' India is planning an imminent military strike",
    "Harvard head apologises as scathing reports on campus prejudice released",
    "Life inside Iraq's 'Forbidden Zone' controlled by Turkey",
    "Xi's real test is not Trump's trade war",
    "Trump calls Bezos as Amazon says no plan to show tariff price rises",
    "Five things you need to make it through a power cut",
    "Sport",
    "PSG pass masters make Rice and Arsenal's fears come true",
    "LIVE: Champions League reaction: Donnarumma's heroics against Arsenal",
    "An Inter legend conquering the world - how Martinez's dream came true",
    "I don't compare myself to Messi - Barca star Yamal",
    "Why the away goals rule no longer counts in Europe",
    "LIVE: Champions League reaction: Donnarumma's heroics against Arsenal",
    "McIlroy to play Scottish Open before Portrush bid",
    "'Disrespectful' dad criticised as Pacers beat Bucks",
    "An Inter legend conquering the world - how Martinez's dream came true",
    "US Politics Unspun"
  ]
}

At first glance, the results from the local LLM might appear identical, but this is not the case. Although the first agent does produce some duplicate headlines, the second agent generates even more duplicates, despite receiving more detailed instructions. In addition, when running both scripts, you will notice that the first agent operates much more quickly.

Browser Use allows users to easily interact with the Internet with just a few lines of code. In this article, we focused on web scraping, but Browser Use offers much more functionality. In general, when you use cloud LLMs as the “brains” of the operation, you can expect better and faster results. However, with powerful enough hardware capable of running local models with over 8B parameters, you could achieve similar results. Overall, Browser Use shows a glimpse into the future of automating web interactions. This is especially evident in its ability to handle dynamic elements that standard tools simply cannot manage.

Boris Delovski

Data Science Trainer

Boris Delovski

Boris is a data science trainer and consultant who is passionate about sharing his knowledge with others.

Before Edlitera, Boris applied his skills in several industries, including neuroimaging and metallurgy, using data science and deep learning to analyze images.