Selenium WebDriver is the industry standard for web automation and testing. With Orchestrator, you can run Selenium scripts against cloud-hosted browser instances without managing browser drivers or infrastructure.

Installation

Install Selenium WebDriver for your preferred language:
pip install selenium requests
You don’t need to install ChromeDriver since you’ll be connecting to Orchestrator’s managed browsers.

Python Integration

Here’s how to connect Selenium WebDriver to an Orchestrator session using Python:
import requests
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def connect_to_orchestrator():
    api_key = 'orch_your_api_key_here'
    
    # Create a new browser session
    session_response = requests.post(
        'https://api.orchestratorhq.com/api/sessions',
        headers={
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json'
        },
        json={
            'session_name': 'Selenium Automation',
            'duration': '1h'
        }
    )

    session = session_response.json()
    session_id = session['id']
    print(f'Session created: {session_id}')

    # Extract CDP URL and convert to Selenium format (session is active when API responds)
    cdp_url = session['cdp_url']
    # Convert ws://host:port/devtools/browser/id to http://host:port
    server_url = cdp_url.replace('ws://', 'http://').split('/devtools')[0]

    # Configure Chrome options for remote debugging
    chrome_options = Options()
    chrome_options.add_experimental_option("debuggerAddress", server_url.replace('http://', ''))

    # Connect to the remote browser
    driver = webdriver.Chrome(options=chrome_options)

    return driver, session_id, api_key

# Usage example
def main():
    driver, session_id, api_key = connect_to_orchestrator()

    try:
        # Your automation code here
        driver.get('https://example.com')
        print(f'Page title: {driver.title}')

        # Take a screenshot
        driver.save_screenshot('example.png')

    finally:
        # Clean up
        driver.quit()

        # Stop the session
        requests.delete(
            f'https://api.orchestratorhq.com/api/sessions/{session_id}',
            headers={'Authorization': f'Bearer {api_key}'}
        )

if __name__ == '__main__':
    main()

Web Scraping Example

Here’s a practical web scraping example using Selenium with Orchestrator:
import requests
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def scrape_products():
    # Connect to Orchestrator session
    orchestrator = OrchestratorSelenium()
    driver = orchestrator.connect_driver()

    try:
        # Navigate to product listing page
        driver.get('https://books.toscrape.com/')

        # Wait for products to load
        wait = WebDriverWait(driver, 10)
        products = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '.product_pod')))

        scraped_products = []

        for product in products[:10]:  # Scrape first 10 products
            try:
                title_element = product.find_element(By.CSS_SELECTOR, 'h3 a')
                title = title_element.get_attribute('title')
                
                price_element = product.find_element(By.CSS_SELECTOR, '.price_color')
                price = price_element.text
                
                rating_element = product.find_element(By.CSS_SELECTOR, '.star-rating')
                rating = rating_element.get_attribute('class').split()[-1]
                
                availability_element = product.find_element(By.CSS_SELECTOR, '.availability')
                availability = availability_element.text.strip()

                scraped_products.append({
                    'title': title,
                    'price': price,
                    'rating': rating,
                    'availability': availability
                })

            except Exception as e:
                print(f'Error scraping product: {e}')
                continue

        print(f'Scraped {len(scraped_products)} products:')
        for product in scraped_products:
            print(f"- {product['title']}: {product['price']} ({product['rating']} stars)")

        # Take screenshot of the page
        driver.save_screenshot('books_page.png')

        return scraped_products

    finally:
        orchestrator.cleanup()

if __name__ == '__main__':
    products = scrape_products()

Form Automation Example

Automate form filling and submission:
from selenium.webdriver.support.ui import Select

def automate_contact_form():
    orchestrator = OrchestratorSelenium()
    driver = orchestrator.connect_driver()

    try:
        # Navigate to contact form
        driver.get('https://httpbin.org/forms/post')

        # Fill text inputs
        name_field = driver.find_element(By.NAME, 'custname')
        name_field.send_keys('John Doe')

        phone_field = driver.find_element(By.NAME, 'custtel')
        phone_field.send_keys('+1-555-123-4567')

        email_field = driver.find_element(By.NAME, 'custemail')
        email_field.send_keys('john.doe@example.com')

        # Select dropdown option
        size_dropdown = Select(driver.find_element(By.NAME, 'size'))
        size_dropdown.select_by_value('medium')

        # Select radio button
        topping_radio = driver.find_element(By.CSS_SELECTOR, 'input[name="topping"][value="bacon"]')
        topping_radio.click()

        # Fill textarea
        comments_field = driver.find_element(By.NAME, 'comments')
        comments_field.send_keys('This is an automated test using Selenium and Orchestrator.')

        # Take screenshot before submission
        driver.save_screenshot('form_filled.png')

        # Submit form
        submit_button = driver.find_element(By.CSS_SELECTOR, 'input[type="submit"]')
        submit_button.click()

        # Wait for response page
        wait = WebDriverWait(driver, 10)
        response_element = wait.until(EC.presence_of_element_located((By.TAG_NAME, 'pre')))

        response_text = response_element.text
        print('Form submission response:', response_text)

        # Take screenshot of result
        driver.save_screenshot('form_result.png')

    finally:
        orchestrator.cleanup()

if __name__ == '__main__':
    automate_contact_form()

Java Integration

Here’s how to use Selenium with Orchestrator in Java:
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.time.Duration;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

public class OrchestratorSelenium {
    private static final String API_KEY = "orch_your_api_key_here";
    private static final String BASE_URL = "https://api.orchestratorhq.com";
    
    private WebDriver driver;
    private String sessionId;
    private HttpClient httpClient;
    private ObjectMapper objectMapper;

    public OrchestratorSelenium() {
        this.httpClient = HttpClient.newHttpClient();
        this.objectMapper = new ObjectMapper();
    }

    public WebDriver connectToOrchestrator() throws Exception {
        // Create session
        String sessionPayload = "{\"session_name\":\"Java Selenium\",\"duration\":\"1h\"}";
        
        HttpRequest createRequest = HttpRequest.newBuilder()
            .uri(URI.create(BASE_URL + "/api/sessions"))
            .header("Authorization", "Bearer " + API_KEY)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(sessionPayload))
            .build();

        HttpResponse<String> createResponse = httpClient.send(createRequest, 
            HttpResponse.BodyHandlers.ofString());

        JsonNode sessionJson = objectMapper.readTree(createResponse.body());
        this.sessionId = sessionJson.get("id").asText();

        System.out.println("Session created: " + sessionId);

        // Configure Chrome options (session is active when API responds)
        String cdpUrl = sessionJson.get("cdp_url").asText();
        String serverUrl = cdpUrl.replace("ws://", "http://").split("/devtools")[0];
        
        ChromeOptions options = new ChromeOptions();
        options.setExperimentalOption("debuggerAddress", serverUrl.replace("http://", ""));

        this.driver = new ChromeDriver(options);
        return driver;
    }

    public void cleanup() {
        if (driver != null) {
            try {
                driver.quit();
            } catch (Exception e) {
                System.err.println("Error quitting driver: " + e.getMessage());
            }
        }

        if (sessionId != null) {
            try {
                HttpRequest deleteRequest = HttpRequest.newBuilder()
                    .uri(URI.create(BASE_URL + "/api/sessions/" + sessionId))
                    .header("Authorization", "Bearer " + API_KEY)
                    .DELETE()
                    .build();

                httpClient.send(deleteRequest, HttpResponse.BodyHandlers.ofString());
            } catch (Exception e) {
                System.err.println("Error stopping session: " + e.getMessage());
            }
        }
    }

    public static void main(String[] args) {
        OrchestratorSelenium orchestrator = new OrchestratorSelenium();

        try {
            WebDriver driver = orchestrator.connectToOrchestrator();

            // Your automation code
            driver.get("https://example.com");
            System.out.println("Page title: " + driver.getTitle());

            // Find and interact with elements
            WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
            WebElement heading = wait.until(ExpectedConditions.presenceOfElementLocated(By.tagName("h1")));
            
            System.out.println("Heading text: " + heading.getText());

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            orchestrator.cleanup();
        }
    }
}

Testing with pytest

Create automated tests using pytest:
import pytest
import requests
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class TestWithOrchestrator:
    @pytest.fixture(scope="class")
    def orchestrator_driver(self):
        """Fixture to create and manage Orchestrator session"""
        api_key = 'orch_your_api_key_here'
        
        # Create session
        session_response = requests.post(
            'https://api.orchestratorhq.com/api/sessions',
            headers={
                'Authorization': f'Bearer {api_key}',
                'Content-Type': 'application/json'
            },
            json={
                'session_name': 'pytest Session',
                'duration': '30m'
            }
        )

        session = session_response.json()
        session_id = session['id']

        # Connect driver (session is active when API responds)
        cdp_url = session['cdp_url']
        server_url = cdp_url.replace('ws://', 'http://').split('/devtools')[0]

        chrome_options = Options()
        chrome_options.add_experimental_option("debuggerAddress", server_url.replace('http://', ''))

        driver = webdriver.Chrome(options=chrome_options)

        yield driver

        # Cleanup
        driver.quit()
        requests.delete(
            f'https://api.orchestratorhq.com/api/sessions/{session_id}',
            headers={'Authorization': f'Bearer {api_key}'}
        )

    def test_homepage_loads(self, orchestrator_driver):
        """Test that homepage loads correctly"""
        driver = orchestrator_driver
        driver.get('https://example.com')
        
        assert 'Example Domain' in driver.title
        
        heading = driver.find_element(By.TAG_NAME, 'h1')
        assert 'Example Domain' in heading.text

    def test_navigation_works(self, orchestrator_driver):
        """Test navigation functionality"""
        driver = orchestrator_driver
        driver.get('https://example.com')
        
        # Check for "More information" link
        wait = WebDriverWait(driver, 10)
        more_info_link = wait.until(
            EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, 'More information'))
        )
        
        assert more_info_link.is_displayed()
        
        # Take screenshot for visual verification
        driver.save_screenshot('navigation_test.png')

    def test_form_submission(self, orchestrator_driver):
        """Test form submission functionality"""
        driver = orchestrator_driver
        driver.get('https://httpbin.org/forms/post')
        
        # Fill form
        driver.find_element(By.NAME, 'custname').send_keys('Test User')
        driver.find_element(By.NAME, 'custemail').send_keys('test@example.com')
        
        # Submit
        driver.find_element(By.CSS_SELECTOR, 'input[type="submit"]').click()
        
        # Verify submission
        wait = WebDriverWait(driver, 10)
        response = wait.until(EC.presence_of_element_located((By.TAG_NAME, 'pre')))
        
        assert 'Test User' in response.text
        assert 'test@example.com' in response.text

if __name__ == '__main__':
    pytest.main([__file__, '-v'])

Best Practices and Error Handling

Debugging Tips

Next Steps