PHPackages                             testingbot/testingbot-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. testingbot/testingbot-php

ActiveLibrary[Testing &amp; Quality](/categories/testing)

testingbot/testingbot-php
=========================

PHP client for the TestingBot API (cross-browser &amp; device testing, screenshots, tunnels, storage, codeless tests).

2.0.0(4w ago)325.7k1Apache-2.0PHPPHP &gt;=8.1CI passing

Since Aug 26Pushed 4w ago1 watchersCompare

[ Source](https://github.com/testingbot/testingbot-php)[ Packagist](https://packagist.org/packages/testingbot/testingbot-php)[ Docs](https://github.com/testingbot/testingbot-php)[ RSS](/packages/testingbot-testingbot-php/feed)WikiDiscussions master Synced yesterday

READMEChangelog (3)Dependencies (7)Versions (7)Used By (1)

TestingBot PHP Client
=====================

[](#testingbot-php-client)

The official PHP client for the [TestingBot API](https://testingbot.com/support/api) — cross-browser &amp; device testing, screenshots, tunnels, app storage and codeless tests.

[![CI](https://github.com/testingbot/testingbot-php/actions/workflows/test.yml/badge.svg)](https://github.com/testingbot/testingbot-php/actions/workflows/test.yml)

Requirements
------------

[](#requirements)

- PHP 8.1 or newer
- The `curl`, `json` and `fileinfo` extensions (all standard)

Installation
------------

[](#installation)

```
composer require testingbot/testingbot-php
```

Getting started
---------------

[](#getting-started)

Grab your key and secret from your [TestingBot account](https://testingbot.com/members/user/edit) and create a client:

```
$client = new TestingBot\Client($key, $secret);

$browsers = $client->browsers()->list();
$test     = $client->tests()->get($webdriverSessionId);
$client->tests()->update($webdriverSessionId, ['name' => 'login test', 'success' => true]);
```

The API is grouped into resources, accessed via methods on the client. Every call returns the decoded JSON response as an array, and throws a typed exception on failure (see [Error handling](#error-handling)).

### Configuration options

[](#configuration-options)

```
$client = new TestingBot\Client($key, $secret, [
    'timeout'         => 90,   // request timeout in seconds
    'connect_timeout' => 30,
    'base_url'        => 'https://api.testingbot.com/v1/',
    'ssl_verify'      => true,
    'user_agent'      => 'my-app/1.0',
]);
```

Resources
---------

[](#resources)

### Tests

[](#tests)

```
$client->tests()->list(0, 10, ['build' => 'ci-42']); // paginated, filterable
$client->tests()->get($sessionId);
$client->tests()->update($sessionId, ['name' => 'checkout', 'success' => false]);
$client->tests()->create(['name' => 'external result', 'success' => true]);
$client->tests()->stop($sessionId);
$client->tests()->delete($sessionId);
```

### Builds

[](#builds)

```
$client->builds()->list(0, 10);
$client->builds()->getTests($buildId);
$client->builds()->delete($buildId);
```

### Storage

[](#storage)

```
$upload = $client->storage()->uploadFile('/path/to/app.apk');   // => ['app_url' => 'tb://...']
$client->storage()->uploadRemoteUrl('https://example.com/app.apk');
$client->storage()->replaceFile($upload['app_url'], '/path/to/new.apk');
$client->storage()->list(0, 10);
$client->storage()->get($upload['app_url']);
$client->storage()->delete($upload['app_url']);
```

### Tunnels

[](#tunnels)

```
$client->tunnels()->list();
$client->tunnels()->getActive();
$client->tunnels()->get($tunnelId);
$client->tunnels()->create();
$client->tunnels()->delete($tunnelId);
```

### User &amp; team

[](#user--team)

```
$client->user()->get();
$client->user()->keys();
$client->user()->update(['first_name' => 'Jane']);

$client->teamManagement()->get();                 // concurrency snapshot
$client->teamManagement()->listUsers(0, 25);
$client->teamManagement()->createUser(['email' => 'dev@acme.com', 'password' => '…']);
$client->teamManagement()->updateUser($userId, ['credits' => 100]);
$client->teamManagement()->resetUserKeys($userId);
```

### Browsers, devices &amp; configuration

[](#browsers-devices--configuration)

```
use TestingBot\Enum\BrowserType;

$client->browsers()->list(BrowserType::Webdriver);
$client->devices()->list('android');
$client->devices()->available();
$client->devices()->get($deviceId);
$client->configuration()->ipRanges();             // no authentication required
```

### Screenshots

[](#screenshots)

```
$batch = $client->screenshots()->create('https://example.com', [1, 2, 3], [
    'resolution' => '1920x1080',
    'fullpage'   => true,
]);
$client->screenshots()->get($batch['id']);
$client->screenshots()->list(0, 10);
```

### Codeless (Lab) tests &amp; suites

[](#codeless-lab-tests--suites)

```
$test = $client->lab()->createTest(['name' => 'smoke', 'url' => 'https://example.com']);
$client->lab()->setSteps($test['lab_test_id'], [
    ['order' => 0, 'cmd' => 'open',  'locator' => '/',    'value' => ''],
    ['order' => 1, 'cmd' => 'click', 'locator' => '#go',  'value' => ''],
]);
$client->lab()->setBrowsers($test['lab_test_id'], [12, 34]);
$job = $client->lab()->trigger($test['lab_test_id']);

$client->labSuites()->create(['name' => 'Regression']);
$client->labSuites()->addTests($suiteId, [1, 2, 3]);
$client->labSuites()->trigger($suiteId);
```

### Jobs (polling)

[](#jobs-polling)

Trigger endpoints return a `job_id` you can poll:

```
$job = $client->lab()->trigger($labTestId);
$final = $client->jobs()->waitForCompletion($job['job_id'], timeout: 300, interval: 5);
```

### Sharing

[](#sharing)

```
$hash = $client->getAuthenticationHash($sessionId); // for building share links
```

Error handling
--------------

[](#error-handling)

Any non-2xx response throws a typed exception; transport failures throw `NetworkException`. All of them implement `TestingBot\Exception\TestingBotExceptionInterface`.

```
use TestingBot\Exception\AuthenticationException;
use TestingBot\Exception\NotFoundException;
use TestingBot\Exception\RateLimitException;
use TestingBot\Exception\ApiException;
use TestingBot\Exception\NetworkException;

try {
    $test = $client->tests()->get($sessionId);
} catch (NotFoundException $e) {
    // 404 — no such test
} catch (AuthenticationException $e) {
    // 401 / 403
} catch (RateLimitException $e) {
    sleep($e->getRetryAfter() ?? 60);
} catch (ApiException $e) {
    error_log($e->getStatusCode() . ': ' . $e->getResponseBody());
} catch (NetworkException $e) {
    // DNS / connection / timeout / TLS
}
```

Migrating from 1.x
------------------

[](#migrating-from-1x)

The 1.x class is still here and every method keeps its name and signature:

```
$api = new TestingBot\TestingBotAPI($key, $secret);
$api->getJob($sessionId);
$api->getTunnels();
```

The one behavioural change in 2.0: **failures now throw** instead of returning an array with an `error` key. Wrap calls in `try/catch` as shown above. From the facade you can reach any new resource via `$api->client()`:

```
$api->client()->screenshots()->create('https://example.com', [1], ['resolution' => '1280x1024']);
```

See [CHANGELOG.md](CHANGELOG.md) for the full list of changes.

Development
-----------

[](#development)

```
composer install
composer test         # unit tests (no credentials needed)
composer phpstan      # static analysis (level 8)
composer cs-fix       # apply coding standards (PSR-12)
```

Integration tests hit the live API and are skipped unless `TB_KEY` and `TB_SECRET` are set:

```
TB_KEY=… TB_SECRET=… composer test:integration
```

Releasing
---------

[](#releasing)

Releases are tag-driven and require **no tokens or secrets**. Packagist syncs new versions from the repository through its GitHub integration, and the release workflow uses the built-in `GITHUB_TOKEN`.

1. Bump `Client::VERSION` and add a `## [x.y.z]` section to `CHANGELOG.md`.
2. Tag and push:

    ```
    git tag 2.0.0
    git push origin 2.0.0
    ```

The [`Release`](.github/workflows/release.yml) workflow then verifies the tag matches `Client::VERSION`, runs the checks, and publishes a GitHub Release with notes taken from `CHANGELOG.md`. Packagist updates on its own once the tag exists.

License
-------

[](#license)

Apache 2.0 — see [LICENSE.APACHE2](LICENSE.APACHE2).

###  Health Score

57

—

FairBetter than 98% of packages

Maintenance94

Actively maintained with recent releases

Popularity29

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity76

Established project with proven stability

 Bus Factor1

Top contributor holds 72.2% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~892 days

Total

5

Last Release

28d ago

Major Versions

1.0.3 → 2.0.02026-06-05

PHP version history (2 changes)1.0.0PHP &gt;=5.4.0

2.0.0PHP &gt;=8.1

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/945169?v=4)[TestingBot](/maintainers/testingbot)[@testingbot](https://github.com/testingbot)

---

Top Contributors

[![delabiejochen](https://avatars.githubusercontent.com/u/42799634?v=4)](https://github.com/delabiejochen "delabiejochen (13 commits)")[![jochen-testingbot](https://avatars.githubusercontent.com/u/137506783?v=4)](https://github.com/jochen-testingbot "jochen-testingbot (5 commits)")

---

Tags

api-clientphp-webdrivertestingbotwebdrivertestingapiseleniumscreenshotscypressappiumtestingbotcross-browser

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/testingbot-testingbot-php/health.svg)

```
[![Health](https://phpackages.com/badges/testingbot-testingbot-php/health.svg)](https://phpackages.com/packages/testingbot-testingbot-php)
```

###  Alternatives

[sauce/sausage

PHP version of the Sauce Labs API

70808.5k3](/packages/sauce-sausage)[appium/php-client

PHP client for Selenium 3.0/Appium 1.0

71676.0k4](/packages/appium-php-client)[simpletest/simpletest

SimpleTest is a framework for unit testing, web site testing and mock objects for PHP.

149368.0k33](/packages/simpletest-simpletest)[noeldemartin/laravel-cypress

Laravel package used for running tests with Cypress.

14185.7k](/packages/noeldemartin-laravel-cypress)[magium/magium

A browser/functional testing suite using Web Driver. Contains low-ish level functionality to quickly build browser/functional tests.

296.8k11](/packages/magium-magium)[magium/magento

Magento-based functionality for the Magium test library

275.4k2](/packages/magium-magento)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
