ScreenshotNeo

BlogGuides

Selenium WebDriver Browser Commands in C#: A Guide

Learn the core Selenium WebDriver commands in C#: navigate, inspect pages, find elements, wait for dynamic content, switch contexts, and clean up.

By the ScreenshotNeo team4 October 20269 min read

Selenium WebDriver browser commands in C# let you start a browser session, navigate between pages, inspect the current page, locate and operate on elements, manage cookies and windows, wait for dynamic content, and close the session. The main interface is IWebDriver; a concrete driver such as ChromeDriver starts the browser. This guide uses Selenium’s official C# example and API references. Check method signatures and browser support against the Selenium package and driver version installed in your project.

1. Create a C# project and start a browser

Install the Selenium WebDriver package and a driver for the browser you plan to control. Selenium’s getting-started guide shows the package setup and a working C# example: Selenium first script. The browser and driver must be compatible with your installed setup.

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;

IWebDriver driver = new ChromeDriver();

try
{
    driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/web-form.html");
    Console.WriteLine(driver.Title);
}
finally
{
    driver.Quit();
}

IWebDriver is the common browser-control interface. Keep the variable typed as that interface when you want the rest of the code to depend less on a specific browser implementation. A concrete driver creates the session.

2. Navigate and inspect the current page

Navigate() gives access to browser navigation commands. GoToUrl loads a URL; browser history commands move within the current session.

driver.Navigate().GoToUrl("https://example.com");

string currentUrl = driver.Url;
string pageTitle = driver.Title;
string pageSource = driver.PageSource;
string currentWindow = driver.CurrentWindowHandle;
IReadOnlyCollection<string> openWindows = driver.WindowHandles;

driver.Navigate().Back();
driver.Navigate().Forward();
driver.Navigate().Refresh();
Command or property Purpose Important detail
Navigate().GoToUrl(url) Load a URL Navigation waits according to the configured page-load strategy.
Url Get or set the current URL Setting it loads a page using HTTP GET.
Title Read the current window’s title It reflects the current browsing context.
PageSource Read a representation of the page DOM It is not guaranteed to reflect JavaScript changes made after load or match the original server response.
CurrentWindowHandle / WindowHandles Identify the selected window and open windows Use handles with SwitchTo() when a new window opens.
Back(), Forward(), Refresh() Use browser history or reload the current page These act on the current browsing context.

3. Find elements and interact with them

Browser commands act on the session. Element commands act on an IWebElement returned by a search. A By locator specifies how Selenium searches: for example, by ID, name, CSS selector, XPath, or tag name.

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;

IWebDriver driver = new ChromeDriver();
try
{
    driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/web-form.html");

    IWebElement textBox = driver.FindElement(By.Name("my-text"));
    IWebElement submitButton = driver.FindElement(By.TagName("button"));

    textBox.SendKeys("Selenium");
    submitButton.Click();

    string message = driver.FindElement(By.Id("message")).Text;
    Console.WriteLine(message);
}
finally
{
    driver.Quit();
}

FindElement is for a result that should exist; if there is no match, Selenium throws an exception. FindElements returns a collection and returns an empty collection when no elements match, so it is useful for optional elements or multiple matches.

IReadOnlyCollection<IWebElement> banners = driver.FindElements(By.CssSelector(".notice"));
if (banners.Count > 0)
{
    Console.WriteLine(banners.First().Text);
}

Common IWebElement operations include Click(), SendKeys(), reading Text, and inspecting properties such as Displayed and Enabled. A stored element reference can become stale if the page replaces that DOM node; locate it again after the page changes.

4. Wait for the condition your next command needs

A navigation command waiting for a page-load state does not guarantee that a JavaScript application has finished rendering or that a control is ready. Selenium’s waiting guide explains this timing issue and recommends against mixing implicit and explicit waits: Selenium waiting strategies.

Use a condition-based explicit wait for the next action. This example waits for a named element to exist:

using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;

var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement searchBox = wait.Until(d => d.FindElement(By.Name("q")));
searchBox.SendKeys("Selenium WebDriver");

Choose a condition that matches the action. Existence may be enough to read text; clicking often requires the element to be visible and enabled. For an application-specific ready state, wait for the actual result or state change the test depends on.

Implicit waits apply globally to element searches; explicit waits poll for a specific condition. Combining them can produce unpredictable total delays. Prefer a consistent explicit-wait strategy for dynamic pages, and avoid adding a global implicit wait on top of it.

5. Manage timeouts, cookies, and windows

Manage() accesses session options, including timeouts, cookies, and window controls. Verify the exact methods available in the Selenium .NET API version in your project. The following are representative C# operations:

// Set navigation and script time limits.
driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(30);
driver.Manage().Timeouts().AsynchronousJavaScript = TimeSpan.FromSeconds(10);

// Work with cookies for the current domain.
driver.Navigate().GoToUrl("https://example.com");
driver.Manage().Cookies.AddCookie(new Cookie("session", "example-value"));
Cookie? sessionCookie = driver.Manage().Cookies.GetCookieNamed("session");

// Maximize the current browser window.
driver.Manage().Window.Maximize();

Cookie operations are domain-bound: navigate to the relevant site before adding a cookie, and follow the application’s cookie requirements. Avoid putting real credentials or session values in source code or logs.

6. Switch to a frame or another window

SwitchTo() changes the target browsing context. Commands after the switch are directed to the selected frame or window. Switch back to the top-level document when you are done with a frame.

// Switch into a frame located on the current page.
IWebElement frame = driver.FindElement(By.CssSelector("iframe"));
driver.SwitchTo().Frame(frame);

// Find elements inside that frame here.
IWebElement insideFrame = driver.FindElement(By.Id("inside-frame"));

// Return to the main document.
driver.SwitchTo().DefaultContent();

For a newly opened window, record the current handle, trigger the action that opens it, then select the new handle. Do not depend on the ordering of handles.

string originalWindow = driver.CurrentWindowHandle;

// Perform an action that opens another window or tab here.

string newWindow = driver.WindowHandles.First(handle => handle != originalWindow);
driver.SwitchTo().Window(newWindow);

// Work in the new window, then switch back when needed.
driver.SwitchTo().Window(originalWindow);

7. Close a window or end the session

Close() closes the currently selected window. If it is the last window, the browser may exit. Quit() ends the WebDriver session and closes all windows associated with it. Use Quit() in a finally block or your test framework’s cleanup hook so a failed assertion does not leave the browser running.

try
{
    // Browser automation steps.
}
finally
{
    driver.Quit();
}

8. Other command families to know

The .NET WebDriver API also includes commands and interfaces for JavaScript execution, screenshots, alerts, keyboard and pointer actions, logs, printing, downloads, and network handling. Driver support varies, so check the official API and the capabilities of your selected browser driver before depending on an advanced command.

  • ExecuteScript and ExecuteAsyncScript run JavaScript in the current browsing context. Prefer normal element interactions for user-facing flows; use scripts when the task requires browser-side JavaScript.
  • Alert commands handle JavaScript dialogs through the selected alert.
  • Actions support more complex pointer and keyboard interactions.
  • Screenshot interfaces capture browser output; capture scope and supported formats depend on the implementation.

Official reference: Selenium .NET API documentation.

9. Troubleshooting common problems

Symptom Likely cause What to do
NoSuchElementException The locator does not match, the page is in a different context, or the element has not appeared yet. Check the locator against the current page, switch into the right frame or window, and wait for the element condition.
StaleElementReferenceException The page replaced or detached the element after it was found. Wait for the page’s update to finish, then locate the element again instead of reusing the old reference.
Click has no effect or is intercepted The element is hidden, disabled, covered by an overlay, or not ready. Wait for visibility and readiness, handle the overlay if it is part of the flow, and confirm the element is enabled before clicking.
Commands target the wrong page region The driver remains in a frame or a different window. Use SwitchTo().DefaultContent() or select the intended window handle.
Test is flaky after navigation Document load completion was mistaken for application readiness. Wait explicitly for the content or state required by the next step.
Wait lasts much longer than expected Implicit and explicit waits are combined, or the requested condition never occurs. Use one wait strategy, set a bounded timeout, and check that the condition can become true.
Browser remains open after a failure Cleanup was skipped on an exception path. Call Quit() from finally or a test framework teardown hook.
Cookie cannot be added The current page is not on the cookie’s domain or the cookie attributes do not fit the site. Navigate to the correct domain first and verify the cookie’s domain and policy requirements.

10. Performance, reliability, and cost

WebDriver commands cross the boundary between your test process and the browser driver, so avoid repeated element searches and page-source reads when a single lookup or focused assertion will do. Use explicit waits with realistic timeouts: overly short waits create intermittent failures, while unbounded or unnecessarily long waits slow feedback when a condition is broken.

Reliability comes from stable locators, checking the state the next action needs, selecting the correct frame or window, and always ending the session. Page-load strategy affects when navigation returns, but it does not replace waits for client-rendered application state. Keep screenshots and logs focused on failures so debugging output does not grow without purpose.

Cost depends on where the browser runs: local browser execution uses local compute, while remote browser infrastructure may be billed by its provider. Selenium’s API documentation does not establish a universal execution price or performance benchmark, so measure your own workload and check your infrastructure provider’s terms.

11. Or skip the browser setup

For a screenshot of a public page, ScreenshotNeo provides a website screenshot API and an MCP server. A single GET request can return PNG, JPEG, WebP, or PDF. It is not a replacement for Selenium’s interactive browser automation commands; it is a direct option when the task is capturing a page image.

Or skip the browser setup: ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));

Cookie and consent banners are accepted like a visitor and more than 60 known consent platforms, newsletter popups, and chat widgets are removed before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers say the page verdict and billing status. The MCP server offers take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is on every plan. Visit ScreenshotNeo or sign up free for 1,000 screenshots a month with no card.

12. FAQ

Does driver.Url navigate to a new page?

Yes. Setting Url loads the address using HTTP GET; Navigate().GoToUrl(url) makes that intent explicit in command form.

Should I use PageSource to inspect every live DOM change?

No. Selenium does not guarantee that it reflects JavaScript modifications made after load. Locate the specific element or state needed by the test.

When should I use Close() instead of Quit()?

Use Close() to close the selected window while continuing a session with other windows. Use Quit() to end the complete driver session.

Can these commands run in any browser?

The interface is designed for different browser implementations, but available behavior depends on the concrete driver, browser, and Selenium version.