Focus On Building Better Applications By Automating Tests In Our Cloud

Instant access to secure, reliable and real browser environments for all of your automated functional and unit testing needs.

Start your free trial

Faster, Easier Test Automation With Zero Setup Or Infrastructure.

Increase your test coverage and innovation by running your tests in our instant access, always-on device cloud.

Test Multiple Devices At Once

With Parallel testing, tests that took hours will now take minutes while they execute concurrently across multiple browsers.

Scale Selenium Instantly

With no infastructure or hassle, our device cloud will scale Selenium or Appium instantly, bringing you stable, reliable testing.

Framework Friendly

There are tons of testing frameworks and tools out there. We try to provide a powerful testing environment that works with all of them.

import unittest
from selenium import webdriver
import requests
from import expected_conditions as EC
from import By
from import WebDriverWait

class LoginForm(unittest.TestCase):
    def setUp(self):

        # Put your username and authey below
        # You can find your authkey at
        self.username = "[email protected]"
        self.authkey  = "12345"

        self.api_session = requests.Session()
        self.api_session.auth = (self.username,self.authkey)

        self.test_result = None

        caps = {}

        caps['name'] = 'Login Form Example'
        caps['build'] = '1.0'
        caps['browser_api_name'] = 'Chrome53'
        caps['os_api_name'] = 'Win10'
        caps['screen_resolution'] = '1024x768'
        caps['record_video'] = 'true'
        caps['record_network'] = 'true'

        # start the remote browser on our server
        self.driver = webdriver.Remote(
            command_executor="http://%s:[email protected]:80/wd/hub"%(self.username,self.authkey)


    def test_CBT(self):
        # We wrap this all in a try/except so we can set pass/fail at the end
            # load the page url
            print('Loading Url')

            # maximize the window - DESKTOPS ONLY
            #print('Maximizing window')

            # we'll start the login process by entering our username
            print('Entering username')
            self.driver.find_element_by_name('username').send_keys([email protected]')
            # then by entering our password
            print('Entering password')
            # now we'll click the login button
            print('Logging in')
            self.driver.find_element_by_css_selector('body > div > div > div > div > form > div.form-actions > button').click()
            # if we've passed the login, we should see the welcome text

            elem = WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.XPATH, '//*[@id=\"logged-in-message\"]/h2'))

            welcomeText = elem.text
            self.assertEqual("Welcome [email protected]", welcomeText)

            print("Taking snapshot")
            snapshot_hash ='' + self.driver.session_id + '/snapshots').json()['hash']

            # if we are still in the try block after all of our assertions that
            # means our test has had no failures, so we set the status to "pass"
            self.test_result = 'pass'

        except AssertionError as e:
            # log the error message, and set the score to "during tearDown()".
            self.api_session.put('' + self.driver.session_id + '/snapshots/' + snapshot_hash,
                data={'description':"AssertionError: " + str(e)})
            self.test_result = 'fail'

    def tearDown(self):
        print("Done with session %s" % self.driver.session_id)
        # Here we make the api call to set the test's score.
        # Pass it it passes, fail if an assertion fails, unset if the test didn't finish
        if self.test_result is not None:
            self.api_session.put('' + self.driver.session_id,
                data={'action':'set_score', 'score':self.test_result})

if __name__ == '__main__':

import org.openqa.selenium.By;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;

import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import junit.framework.Assert;

class LoginFormTest {

    static String username = ""; // Your username
    static String authkey = "12345";  // Your authkey
    String testScore = "unset";

    public static void main(String[] args) throws Exception {
        LoginFormTest myTest = new LoginFormTest();

        DesiredCapabilities caps = new DesiredCapabilities();

        caps.setCapability("name", "Login Form Example");
        caps.setCapability("build", "1.0");
        caps.setCapability("browser_api_name", "Chrome53");
        caps.setCapability("os_api_name", "Win10");
        caps.setCapability("screen_resolution", "1024x768");
        caps.setCapability("record_video", "true");
        caps.setCapability("record_network", "true");

        RemoteWebDriver driver = new RemoteWebDriver(new URL("http://" + username + ":" + authkey +""), caps);

        // we wrap the test in a try catch loop so we can log assert failures in our system
        try {

            // load the page url
            System.out.println("Loading Url");
            // maximize the window - DESKTOPS ONLY
            //System.out.println("Maximizing window");
            // complete a short login form
            // first by entering the username
            System.out.println("Entering username");
            driver.findElementByName("username").sendKeys("[email protected]");
            // then by entering the password
            System.out.println("Entering password");
            // then by clicking the login button
            System.out.println("Logging in");
            driver.findElementByCssSelector("div.form-actions > button").click();
            // let's wait here to ensure the page has loaded completely
            WebDriverWait wait = new WebDriverWait(driver, 10);
            // Let's assert that the welcome message is present on the page. 
            // if not, an exception will be raised and we'll set the score to fail in the catch block.
            String welcomeMessage = driver.findElementByXPath("//*[@id=\"logged-in-message\"]/h2").getText();
            Assert.assertEquals("Welcome [email protected]", welcomeMessage);
            // if we get to this point, then all the assertions have passed
            // that means that we can set the score to pass in our system
            myTest.testScore = "pass"; 
        catch(AssertionError ae) {

            // if we have an assertion error, take a snapshot of where the test fails
            // and set the score to "fail"
            String snapshotHash = myTest.takeSnapshot(driver.getSessionId().toString());
            myTest.setDescription(driver.getSessionId().toString(), snapshotHash, ae.toString());
            myTest.testScore = "fail";
        finally {

            System.out.println("Test complete: " + myTest.testScore);

            // here we make an api call to actually send the score 
            myTest.setScore(driver.getSessionId().toString(), myTest.testScore);
            // and quit the driver

    public JsonNode setScore(String seleniumTestId, String score) throws UnirestException {
        // Mark a Selenium test as Pass/Fail
        HttpResponse response = Unirest.put("{seleniumTestId}")
                .basicAuth(username, authkey)
                .routeParam("seleniumTestId", seleniumTestId)
                .field("score", score)
        return response.getBody();

    public String takeSnapshot(String seleniumTestId) throws UnirestException {
         * Takes a snapshot of the screen for the specified test.
         * The output of this function can be used as a parameter for setDescription()
        HttpResponse response ="{seleniumTestId}/snapshots")
                .basicAuth(username, authkey)
                .routeParam("seleniumTestId", seleniumTestId)
        // grab out the snapshot "hash" from the response
        String snapshotHash = (String) response.getBody().getObject().get("hash");
        return snapshotHash;
    public JsonNode setDescription(String seleniumTestId, String snapshotHash, String description) throws UnirestException{
         * sets the description for the given seleniemTestId and snapshotHash
        HttpResponse response = Unirest.put("{seleniumTestId}/snapshots/{snapshotHash}")
                .basicAuth(username, authkey)
                .routeParam("seleniumTestId", seleniumTestId)
                .routeParam("snapshotHash", snapshotHash)
                .field("description", description)
        return response.getBody();
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using NUnit.Framework;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium;

namespace LoginFormTest
    class LoginFormTest
        // put your username and authkey here:
        public static string username = "[email protected]";
        public static string authkey = "12345";

        static void Main(string[] args)
            var cbtapi = new CBTApi();

            // Start by setting the capabilities
            var caps = new DesiredCapabilities();
            caps.SetCapability("name", "Login Form Example");
            caps.SetCapability("build", "1.0");
            caps.SetCapability("browser_api_name", "Edge20");
            caps.SetCapability("os_api_name", "Win10");
            caps.SetCapability("screen_resolution", "1024x768");
            caps.SetCapability("record_video", "true");
            caps.SetCapability("record_network", "true");

            caps.SetCapability("username", username);
            caps.SetCapability("password", authkey);

            // Start the remote webdriver
            RemoteWebDriver driver = new RemoteWebDriver(new Uri(""), caps, TimeSpan.FromSeconds(180));

            // wrap the rest of the test in a try-catch for error logging via the API
                // Maximize the window - DESKTOPS ONLY
                // driver.Manage().Window.Maximize();
                // Navigate to the URL
                // Check the title
                Console.WriteLine("Entering username");
                driver.FindElementByName("username").SendKeys("[email protected]");

                // then by entering the password
                Console.WriteLine("Entering password");

                // then by clicking the login button
                Console.WriteLine("Logging in");
                driver.FindElementByCssSelector("div.form-actions > button").Click();

                // let's wait here to ensure that the page has loaded completely
                WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
                wait.Until(drv => driver.FindElement(By.XPath("//*[@id=\"logged-in-message\"]/h2")));
                // Let's assert that the welcome message is present on the page. 
                // if not, an exception will be raised and we'll set the score to fail in the catch block.
                string welcomeMessage = driver.FindElementByXPath("//*[@id=\"logged-in-message\"]/h2").Text;
                Assert.AreEqual("Welcome [email protected]", welcomeMessage);
                cbtapi.setScore(driver.SessionId.ToString(), "pass");
            catch (AssertionException ex)

                var snapshotHash = cbtapi.takeSnapshot(driver.SessionId.ToString());
                cbtapi.setDescription(driver.SessionId.ToString(), snapshotHash, ex.ToString());
                cbtapi.setScore(driver.SessionId.ToString(), "fail");
                Console.WriteLine("caught the exception : " + ex);
                throw new AssertionException(ex.ToString());

    public class CBTApi

        public string BaseURL = "";

        public string username = LoginFormTest.username;
        public string authkey = LoginFormTest.authkey;

        public string takeSnapshot(string sessionId)
            // returns the screenshot hash to be used in the setDescription method.
            // create the POST request object pointed at the snapshot endpoint
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(BaseURL + "/" + sessionId + "/snapshots");
            Console.WriteLine(BaseURL + "/" + sessionId);
            request.Method = "POST";
            request.Credentials = new NetworkCredential(username, authkey);
            request.ContentType = "application/x-www-form-urlencoded";
            request.UserAgent = "HttpWebRequest";
            // Execute the request
            var response = (HttpWebResponse)request.GetResponse();
            // store the response
            var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
            // parse out the snapshot Hash value 
            var myregex = new Regex("(?<=\"hash\": \")((\\w|\\d)*)");
            var snapshotHash = myregex.Match(responseString).Value;
            return snapshotHash;

        public void setDescription(string sessionId, string snapshotHash, string description)
            // encode the data to be written
            ASCIIEncoding encoding = new ASCIIEncoding();
            var putData = encoding.GetBytes("description=" + description);
            // create the request
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(BaseURL + "/" + sessionId + "/snapshots/" + snapshotHash);
            request.Method = "PUT";
            request.Credentials = new NetworkCredential(username, authkey);
            request.ContentType = "application/x-www-form-urlencoded";
            request.UserAgent = "HttpWebRequest";
            // write data to stream
            Stream newStream = request.GetRequestStream();
            newStream.Write(putData, 0, putData.Length);
            WebResponse response = request.GetResponse();

        public void setScore(string sessionId, string score)
            string url = BaseURL + "/" + sessionId;
            // encode the data to be written
            ASCIIEncoding encoding = new ASCIIEncoding();
            string data = "action=set_score&score=" + score;
            byte[] putdata = encoding.GetBytes(data);
            // Create the request
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "PUT";
            request.Credentials = new NetworkCredential(username, authkey);
            request.ContentLength = putdata.Length;
            request.ContentType = "application/x-www-form-urlencoded";
            request.UserAgent = "HttpWebRequest";
            // Write data to stream
            Stream newStream = request.GetRequestStream();
            newStream.Write(putdata, 0, putdata.Length);

var webdriver = require('selenium-webdriver');
var SeleniumServer = require('selenium-webdriver/remote').SeleniumServer;
var request = require('request');
var remoteHub = '';

var username = [email protected]'; //replace with your email address 
var authkey = '12345'; //replace with your authkey  

var caps = {
    name : 'Login Form Example',
    build :  '1.0',
    browser_api_name : 'IE10', 
    os_api_name : 'Win7x64-C2', 
    screen_resolution : '1024x768',
    record_video : 'true',
    record_network : 'true',
    browserName : 'internet explorer', // <---- this needs to be the browser type in lower case: firefox, internet explorer, chrome, opera, or safari
    username : username,
    password : authkey

var sessionId = null;

//register general error handler
webdriver.promise.controlFlow().on('uncaughtException', webdriverErrorHandler);

console.log('Connection to the CrossBrowserTesting remote server');

var driver = new webdriver.Builder()

//console.log('driver is ', driver)

// All driver calls are automatically queued by flow control.
// Async functions outside of driver can use call() function.
console.log('Waiting on the browser to be launched and the session to start');

    sessionId = session.id_; //need for API calls
    console.log('Session ID: ', sessionId); 
    console.log('See your test run at:' + sessionId)

//load your URL

//take snapshot via cbt api;

 //find checkout and click it 
driver.findElement("username")).sendKeys("[email protected]");

//send keys to element to enter text

//take snapshot via cbt api;

//click the archive button

//wait on logged in message
driver.wait(webdriver.until.elementLocated("logged-in-message")), 10000);

//take snapshot via cbt api;

//quit the driver

//set the score as passing, null, 'pass').then(function(result){
    console.log('set score to pass')

//Call API to set the score
function setScore(score) {

    //webdriver has built-in promise to use
    var deferred = webdriver.promise.defer();
    var result = { error: false, message: null }

    if (sessionId){
            method: 'PUT',
            uri: '' + sessionId,
            body: {'action': 'set_score', 'score': score },
            json: true
        function(error, response, body) {
            if (error) {
                result.error = true;
                result.message = error;
            else if (response.statusCode !== 200){
                result.error = true;
                result.message = body;
                result.error = false;
                result.message = 'success';

        .auth(username, authkey);
        result.error = true;
        result.message = 'Session Id was not defined';

    return deferred.promise;

//Call API to get a snapshot 
function takeSnapshot() {

    //webdriver has built-in promise to use
    var deferred = webdriver.promise.defer();
    var result = { error: false, message: null }
    if (sessionId){

            '' + sessionId + '/snapshots', 
            function(error, response, body) {
                if (error) {
                    result.error = true;
                    result.message = error;
                else if (response.statusCode !== 200){
                    result.error = true;
                    result.message = body;
                    result.error = false;
                    result.message = 'success';
                //console.log('fulfilling promise in takeSnapshot')
        result.error = true;
        result.message = 'Session Id was not defined';
        deferred.fulfill(result); //never call reject as we don't need this to actually stop the test

    return deferred.promise;

//general error catching function
function webdriverErrorHandler(err){

    console.error('There was an unhandled exception! ' + err);

    //if we had a session, end it and mark failed
    if (driver && sessionId){
            console.log('set score to fail')
require "selenium-webdriver"
require "rest-client"
require "test-unit"

class LoginFormTest < Test::Unit::TestCase
	def test_login_form_test
			username = ""
			authkey = "12345"

			caps =

			caps["name"] = "Login Form Example"
			caps["build"] = "1.0"
			caps["browser_api_name"] = "Chrome53"
			caps["os_api_name"] = "Win8"
			caps["screen_resolution"] = "1024x768"
			caps["record_video"] = "true"
			caps["record_network"] = "true"

			driver = Selenium::WebDriver.for(:remote,
			:url => "http://#{username}:[email protected]:80/wd/hub",
			:desired_capabilities => caps)

			session_id = driver.session_id

		    score = "pass"
		    cbt_api =
		    # maximize the window - DESKTOPS ONLY

		    puts "Loading URL""")

		    # start login process by entering username
		    puts "Entering username"
		    driver.find_element(:name, "username").send_keys("[email protected]")

		    # then we'll enter the password
		    puts "Entering password"
		    driver.find_element(:name, "password").send_keys("test123")

		    # then we'll click the login button
		    puts "Logging in"
		    driver.find_element(:css, "div.form-actions > button").click

		    # let's wait here to ensure that the page is fully loaded before we move forward
		    wait = => 10)
		    wait.until {
		    	driver.find_element(:xpath, "//*[@id=\"logged-in-message\"]/h2")

		    # if we passed the login, then we should see some welcomeText
		    welcomeText = driver.find_element(:xpath, "//*[@id=\"logged-in-message\"]/h2").text
		    assert_equal("Welcome [email protected]", welcomeText)

		    puts "Taking Snapshot"
		    cbt_api.setScore(session_id, "pass")

		rescue Exception => ex
		    puts ("#{ex.class}: #{ex.message}")
		    cbt_api.setScore(session_id, "fail")

class CBT_API
	@@username = ''
	@@authkey = '12345'
	@@BaseUrl =   "https://#{@@username}:#{@@[email protected]/api/v3"
	def getSnapshot(sessionId)
	    # this returns the the snapshot's "hash" which is used in the
	    # setDescription function
	    response = + "/selenium/#{sessionId}/snapshots",
	    snapshotHash = /(?<="hash": ")((\w|\d)*)/.match(response)[0]
	    return snapshotHash

	def setDescription(sessionId, snapshotHash, description)
	    response = RestClient.put(@@BaseUrl + "/selenium/#{sessionId}/snapshots/#{snapshotHash}",

	def setScore(sessionId, score)
	    # valid scores are 'pass', 'fail', and 'unset'
	    response = RestClient.put(@@BaseUrl + "/selenium/#{sessionId}",


Automate With The Language Of Your Choice

We'll show you the way with examples and repositories in Java, Python, C#, NodeJS, PHP, and Ruby. Interact with testing frameworks like Cucumber, Behat and more with CrossBrowserTesting. Browser Testing has never felt so...automatic.

GitHub Examples

Automate Your Functional Browser Testing On Real Browsers & Devices

Combine the power of traditional testing tools with the flexibility of a 100% real, always-on testing environment.

Javascript Unit Testing

Run your Javascript classes against our entire device lab, ensuring your site's functionality is working all the time.

Powerful Test Reporting

Set tests to Pass or Fail, share screenshots, session recordings, and test results with Slack, HipChat, Jira, and email.

Local, Secure Testing

Using our Local Tunnel, you can run your test automation behind your firewall, on your local machine, or across a proxy server.

Fits Easily In Your Continuous Integration Process.

Use CrossBrowserTesting within your deployment process, allowing for a larger degree of speed and confidence when shipping products and features. We'll work with your CI or Build server to execute Selenium, Appium, or test scripts using our API with little set-up.

CI Integrations