Skip to content

Cypress reporter configuration

Every setting of @probara/cypress-reporter is an option of the reporter in the Cypress config (reporterOptions), and most have a PROBARA_* environment variable too. Keep the token in the environment, the project in the config (or the environment), and set the rest where it fits your pipeline.

  1. Create an app token from the Cypress card in Workspace › Integrations (get started) and store it as a CI secret named PROBARA_API_TOKEN.
  2. Set the Project ID: projectId in reporterOptions, or PROBARA_PROJECT. A Project ID is a capital letter, then capital letters or digits (SHOP, E2E): any other value turns reporting off with an error.
  3. Register the reporter, the plugin and the support file (registration). Everything else has a default. The run is named after the CI build, and its branch, commit and build URL come from the CI on their own.

Do not put the token in the Cypress config: the config is committed. apiToken exists for code that reads the token from its own secret store.

The reporter registers in three places, each with its own job:

cypress.config.js
const { defineConfig } = require('cypress');
const { probaraNodeEvents } = require('@probara/cypress-reporter/setup');
module.exports = defineConfig({
e2e: {
reporter: '@probara/cypress-reporter',
reporterOptions: { projectId: 'SHOP' },
setupNodeEvents(on, config) {
return probaraNodeEvents(on, config);
},
},
});
cypress/support/e2e.js
import '@probara/cypress-reporter/support';
RegistrationWhat it isWhat it turns on
reporter and reporterOptionsThe Mocha reporter Cypress builds for every specEvery test event: one result per attempt, the keys, the screenshots of each attempt
setupNodeEvents (@probara/cypress-reporter/setup)The plugin, in the process that loads the configThe Probara run (created, then closed at the end), the screenshots and the video, the browser parameter
The support file (@probara/cypress-reporter/support)The browser side, next to your specsThe probara.* helpers, captureOutput and run selection

The plugin reads the same reporterOptions Cypress hands the reporter, so it needs no settings of its own. Return the config it returns from setupNodeEvents, as probaraNodeEvents(on, config) does: that config is how its settings reach the browser.

What is missingWhat happens
NothingEverything: one run for the whole cypress run, closed at the end, with the screenshots of every failed attempt, the video and the probara.* helpers
The pluginEvery result is still sent, but in one run per spec, each closed as its spec ends. No screenshot, no video, and no probara.* helper. One warning names what is missing
The support fileResults, screenshots and the video as usual. Every probara.* call does nothing, captureOutput captures nothing, run selection skips nothing
The reporterNothing is reported at all: Cypress never builds this reporter

Cypress keeps one handler per event: when two plugins register after:run (or before:run, before:spec, after:spec, after:screenshot) with the same on, only the last one runs, and the other is dropped without a word (cypress#22428). Tasks are the exception: Cypress merges them. When another plugin registers any of those events, such as cypress-split, hand every plugin the on of cypress-on-fix, which runs every handler in the order they were registered:

cypress.config.js
const { defineConfig } = require('cypress');
const { probaraNodeEvents } = require('@probara/cypress-reporter/setup');
module.exports = defineConfig({
e2e: {
reporter: '@probara/cypress-reporter',
reporterOptions: { projectId: 'SHOP' },
setupNodeEvents(cypressOn, config) {
const on = require('cypress-on-fix')(cypressOn);
require('cypress-split')(on, config);
probaraNodeEvents(on, config);
on('after:run', () => {
// Your own handler: it runs too.
});
return config;
},
},
});

probaraNodeEvents adds its settings to config itself, so returning config at the end keeps them, together with what the other plugins changed. What each lost event costs is in troubleshooting.

Cypress runs one reporter, so this one replaces the per-test lines of the default spec reporter. To keep them, or to write JUnit XML at the same time, register cypress-multi-reporters and put this reporter’s options under probaraCypressReporterReporterOptions, the key it builds from the reporter’s name. The plugin reads them from the same place:

cypress.config.js
module.exports = defineConfig({
e2e: {
reporter: 'cypress-multi-reporters',
reporterOptions: {
reporterEnabled: 'spec, @probara/cypress-reporter',
probaraCypressReporterReporterOptions: { projectId: 'SHOP' },
},
setupNodeEvents(on, config) {
return probaraNodeEvents(on, config);
},
},
});

The first source that sets a value wins:

OrderSourceExample
1An option of the reporter in the Cypress config{ run: { name: 'Release 2.4' } }
2A PROBARA_* variablePROBARA_RUN_NAME=Nightly
3CI detectionCI #42 from the workflow and run number
4The defaultAutomated run 2026-09-29 14:05 UTC
  • An option set to undefined never hides its variable, and a blank variable counts as unset. To let a variable override an option, leave the option out (or pass process.env.X ?? default).
  • Booleans accept true, 1, yes, on and false, 0, no, off. Lists are comma-separated in variables (PROBARA_RUN_TAGS=nightly,smoke).
  • CI detection only fills the run’s name and its source (branch, commit, build URL, and in GitHub Actions the workflow run that groups parallel jobs). What each CI fills in is in CI providers.

Options and variables can be mixed. This config sets the project and tags:

reporterOptions: { projectId: 'SHOP', run: { tags: ['e2e', 'nightly'] } },

and the pipeline adds the run’s environment and name:

Terminal window
PROBARA_ENVIRONMENT=staging PROBARA_RUN_NAME=Nightly npx cypress run
OptionVariableTypeDefaultWhat it does
enabledPROBARA_ENABLEDbooleanonfalse turns reporting off: nothing is sent, and nothing is logged
apiTokenPROBARA_API_TOKENstringnone (required)The app token. Keep it in the environment
projectIdPROBARA_PROJECTstringnone (required)The Project ID (capital letters and digits), such as SHOP
baseUrlPROBARA_BASE_URLstringhttps://app.probara.netThe Probara to report to (self-hosted)
run.ulidPROBARA_RUN_ULIDstringnone: a new runReport into an existing run (an existing run)
run.namePROBARA_RUN_NAMEstringthe CI build name, else Automated run <date> <time> UTCName of a new run
run.descriptionPROBARA_RUN_DESCRIPTIONstringnoneDescription of a new run
run.environmentPROBARA_ENVIRONMENTstringnoneEnvironment of a new run by name, created when none matches
run.environmentIdPROBARA_ENVIRONMENT_IDstringnoneEnvironment of a new run by ULID
run.milestonePROBARA_MILESTONEstringnoneMilestone of a new run by display id (M-3) or name
run.milestoneIdPROBARA_MILESTONE_IDstringnoneMilestone of a new run by ULID
run.planPROBARA_PLANstringnoneTest plan of a new run by display id (PLAN-2) or name: the run starts with its cases
run.configurationsPROBARA_CONFIGURATIONS{ group, name }[]noneConfigurations of a new run by name (Browser=Chrome,OS=Linux), each group once
run.configurationUlidsPROBARA_CONFIGURATION_ULIDSstring[]noneConfigurations of a new run by ULID
run.tagsPROBARA_RUN_TAGSstring[]noneTags of a new run
run.ulidsPROBARA_RUN_ULIDSRecord<string, string>noneThe run to reuse in each project (WEB=<ulid>,API=<ulid>)
projectsPROBARA_PROJECTSstring[]noneOther projects results may go to (WEB,API) (several projects)
source—false | object (GitHub fields below)detected from the CIfalse sends no source; an object overrides the detected fields one by one
source.branchPROBARA_BRANCHstringdetected from the CIBranch of the run source
source.commitPROBARA_COMMITstringdetected from the CICommit of the run source
source.buildUrlPROBARA_BUILD_URLstringdetected from the CICI build URL of the run source
createMissingCasesPROBARA_CREATE_MISSING_CASESbooleantrueCreate a case for a test that matches none
suiteUlidPROBARA_SUITE_ULIDstringthe project rootSuite that created cases go under
closeRunPROBARA_CLOSE_RUNbooleantrue for a new run, false for a reused oneClose the run at the end
closeRuns—Record<string, boolean>noneClose the run of each project ({ SHOP: true, WEB: false }) when closeRun is not set
uploadAttachmentsPROBARA_UPLOAD_ATTACHMENTSbooleantruefalse uploads no file
keyIncludesFilePROBARA_KEY_INCLUDES_FILEbooleantrueStart each automation key with the spec file (keyIncludesFile)
captureOutputPROBARA_CAPTURE_OUTPUTbooleanfalseAttach each test’s console output as stdout.log and stderr.log (captureOutput)
attachScreenshotsPROBARA_ATTACH_SCREENSHOTSbooleantrueAttach the screenshot of each failed attempt (attachScreenshots)
attachVideosPROBARA_ATTACH_VIDEOSbooleanfalseAttach the video of a spec to its failed results (attachVideos)
browserAsParameterPROBARA_BROWSER_AS_PARAMETERbooleantrueSend the browser Cypress runs as a browser parameter (browserAsParameter)
issueUrlTemplatePROBARA_ISSUE_URL_TEMPLATEstringnoneThe URL each probara.issue(id) becomes, with %s for the id (issueUrlTemplate)
runCasesOnlyPROBARA_RUN_CASES_ONLYbooleanfalseRun only the tests of the cases of run.ulid (runCasesOnly)
statusMappingPROBARA_STATUS_MAPPING{ passed, failed, skipped, blocked }noneSend a status as another (failed=blocked) (statuses)
statusFilterPROBARA_STATUS_FILTERstring[]noneSend no result with these statuses, after the mapping (skipped)
resultsFilePROBARA_RESULTS_FILEstringnoneJSON file for what could not be sent (results file)
assignFailedToPROBARA_ASSIGN_FAILED_TOstring[]noneAssign each failed result without an assignee to one of these members, in turn (ana@example.com,bo@example.com)
debugPROBARA_DEBUGbooleanfalseLog every request (debugging)
rootDir—stringCypress’s projectRootDirectory the spec paths of automation keys are relative to (keyIncludesFile)
chunkSize—number500Results per report request, 1 to 500
timeoutMs—number30000Timeout of one HTTP attempt, in milliseconds, 1 to 600000
maxRetries—number4Retries of a failed request, 0 to 10
attachmentConcurrency—number2Results whose attachments upload at the same time, 1 to 8

The reporter sends its own name and version in the User-Agent (such as probara-cypress-reporter/0.1.0); there is no option for it.

In GitHub Actions the source also gets these fields, detected from GITHUB_* variables:

OptionVariableTypeDefaultWhat it does
source.provider—stringdetected from GitHub Actionsgithub_actions (detected) or other
source.repository—stringdetected from GitHub ActionsRepository of the run source, owner/name
source.commitAuthor—stringdetected from GitHub ActionsWho triggered the build
source.pullRequestNumber—numberdetected from GitHub ActionsPull request of the build
source.workflow—stringdetected from GitHub ActionsCI workflow of the run source
source.ciRunId—stringdetected from GitHub ActionsCI run id: the jobs of one GitHub Actions run share one run
source.ciRunAttempt—numberdetected from GitHub ActionsAttempt of the CI run: a re-run reports into a run of its own
source.ciJob—stringdetected from GitHub ActionsCI job of the run source

For code and tests, the reporter also takes the seams of @probara/core. They have no variable, and a Cypress config rarely needs them:

OptionTypeDefaultWhat it does
logger{ debug, info, warn, error }[probara] lines on stdoutWhere the reporter logs
envRecord<string, string>process.envWhere PROBARA_* and CI variables are read from
fetchfunctionthe global fetchThe HTTP client
sleepfunctionsetTimeoutWaits between retries
randomfunctionMath.randomJitter of the retry backoff
nowfunctionthe current timeClock of the default run name and of Retry-After dates

An option the reporter does not know is left out with a warning, and reporting goes on:

reporterOptions: { projectId: 'SHOP', captureOutputs: true },
$ npx cypress run
[probara] Ignored the unknown option "captureOutputs" of @probara/cypress-reporter
[probara] Sending 3 results of 3 tests (3 passed, 0 failed, 0 skipped, 0 blocked)
[probara] Recorded 3 results (2 new cases, 0 unmatched) in R-1 (closed): https://app.probara.net/projects/SHOP/runs/R-1

Each test is matched to its case by an automation key: the spec file relative to rootDir (Cypress’s projectRoot), then > between spaces, then the describe titles and the it title joined by spaces, without the case ids: cypress/e2e/cart.cy.js > Cart adds an item. That is the key probara import junit gives the same test on the report of Cypress’s junit reporter or of cypress-junit.

keyIncludesFile: false leaves the spec file out, like a JUnit report written without the file attribute of its root suite. Switch to it when your cases were imported from such reports, so each test keeps its case. A test then gets the same key as a test with the same describe titles and title in another spec.

reporterOptions: { projectId: 'SHOP', keyIncludesFile: false },
Cart adds an item
Login logs in with a valid password

Changing keyIncludesFile changes every key: tests that name no case in their titles then create new cases. A case the report creates goes in a suite named after the spec and its describe blocks or, with keyIncludesFile: false, after its describe blocks alone. Neither --spec nor Cypress’s folder options change a key (linking).

captureOutput: true attaches what each test writes to the browser console with console.log, console.info and console.debug as stdout.log, and with console.warn and console.error as stderr.log. The browser console still prints everything. It needs the support file: without it, nothing is captured. What is and is not captured is in console output.

attachScreenshots: true (the default) attaches the screenshot Cypress takes of a failed attempt to the result of that attempt, as an image/png. It needs the plugin, which is what receives the screenshots from Cypress. With false, none is attached, and Cypress still takes them where it always does (screenshots).

attachVideos: true attaches the video of a spec to every failed result of that spec (a blocked one too), under the name of the spec file, as a video/mp4. It needs video: true in the Cypress config and the plugin. It is off by default because of the cost: one upload per failed result, and video files are large (the video of a spec).

browserAsParameter: true (the default) sends the name of the browser Cypress runs (electron, chrome, firefox, edge) as a browser parameter of every result:

{
"automationKey": "cypress/e2e/cart.cy.js > Cart adds an item",
"parameters": { "browser": "electron" }
}

It never enters the key, so a suite run on two browsers records into one case. The browser parameter selects a run case only when the case declares a browser parameter; otherwise it stays on the result for display. The browser and the attempt are context: they are shown on the result, and they never become a parameter of a case a report creates. The plugin is what learns the browser: without it there is no browser parameter.

probara.issue(id) names an issue of your tracker: issueUrlTemplate turns it into a link of the result, named by the id, with the URL-encoded id in place of %s (https://jira.example.com/browse/%s). The template is an http or https URL with %s; any other value turns reporting off with an error. Without a template, issues are left out with a warning (links).

runCasesOnly: true (or PROBARA_RUN_CASES_ONLY=true) runs only the tests of the cases of the run run.ulid (PROBARA_RUN_ULID), and reports into that run, leaving it open. It needs both the plugin and the support file. Turn it on per job with the variables rather than in the config: with the option in the config, every job without a run ULID warns and runs every test. Run selection has the matching rules and every fallback.

SetupWhat the reporter does
No token and no project, or enabled: falseStays off and quiet: nothing is sent, and nothing is logged (but at debug).
Only one of them, or an invalid valueReporting is off; each problem is logged, and the tests run as usual.
A token and a project, every value validReports.

A value of the wrong type (such as run.tags: 'nightly' instead of a list) is an invalid value:

reporterOptions: { projectId: 'SHOP', run: { tags: 'nightly' } },
$ npx cypress run
[probara] Probara reporting is off: run.tags must be a list of strings

Problems name the option or the variable at fault, never its value, so a token never shows up.

Set enabled: false or PROBARA_ENABLED=false, or leave the token out: the reporter sends nothing and stays quiet. Builds of pull requests from forks get no secrets, so they report nothing on their own. To keep what a run could not send, even with reporting off, set a results file.

Point the reporter at another Probara with baseUrl or PROBARA_BASE_URL: the URL of the app, without a path. Requests go to that host and nowhere else. For proxies and private certificate authorities, see network.

The reporter talks HTTPS to one host, the base URL, from Node.js: the browser that runs your specs never calls Probara.

SetupProcess that sendsWhen
The plugin registered (the usual setup)The plugin’s, on the Node.js that starts cypressEverything when the run ends: the reports, then the attachment uploads, then the close
No pluginThe reporter’s, inside Cypress, on the Node.js Cypress bundlesEach spec’s results when that spec ends, into a run of its own
runCasesOnlyThe plugin’sBefore the first spec: read the case keys of the run, 200 cases per page until the last page

Nothing is sent while the tests run. Cypress waits for the plugin before it exits, so the time the requests take, retries included, is part of the cypress run command. With runCasesOnly, the case keys are read once per cypress run; when they cannot be read after the retries, every test runs and is reported, with one warning.

SettingDefaultRangeWhat it bounds
timeoutMs30000 ms1 to 600000One attempt of a request, the response body included
uploads120000 ms or timeoutMs if larger—One attempt of an attachment upload (a large file on a slow link)

A timed-out attempt is retried like a network error.

AnswerWhat happens
Network error, timeout, 408, 429, 500, 502, 503, 504Retried
409 with a Retry-After (the same request is still in flight)Retried
A 201 whose body never arrivedRetried; the idempotency key replays it
Any other answer (400, 401, 403, 404, 409, 413, 422…)Not retried: the request fails
  • maxRetries (0 to 10, default 4) sets the retries after the first attempt: 5 attempts in all by default.
  • The wait before retry n is 1 s × 2ⁿ⁻¹, at most 30 s, plus up to 20 % of random jitter.
  • A Retry-After header (seconds or an HTTP date) replaces that wait, capped at 120 s.
  • Each retry is logged, with the attempt and the wait.

With the defaults, a report that keeps failing gives up after about 15 s of waiting (1 + 2 + 4 + 8 s, up to 18 s with the jitter), plus the attempts themselves, each at most timeoutMs. The worst case is a Retry-After on every answer: 120 s before each retry, so 8 minutes of waiting with the default 4 retries (20 minutes with maxRetries: 10), plus up to 5 attempts of 30 s. That is per request, and a failed report stops the later ones of its project. Lower maxRetries or timeoutMs to bound a CI step.

Probara limits API requests per organization (60 requests per minute on Free, 1,200 on Pro, and 3,000 on Enterprise), for every token of the organization together. What a run costs:

RequestHow many
Case keys1 per 200 cases of the run, only with runCasesOnly
Report1 per chunk of up to 500 results (chunkSize)
Attachment stage1 per result with files (per 20 files or 64 MiB)
Attachment commit1 per result with files
Close1, when attachments were queued (otherwise the last report closes the run)

A run of 2000 attempts without files costs 4 requests; one where 100 failed attempts attach their screenshot costs about 200 more. Without the plugin, every spec is a run of its own and pays these requests on its own. 429 answers are retried after their Retry-After. To spread uploads, lower attachmentConcurrency; to send fewer files, attach only what matters, or set uploadAttachments: false.

  • Results go out in chunks of chunkSize (1 to 500, default 500), one after another, in the order Cypress ended the specs, each spec’s attempts in order. A run case keeps the last outcome recorded, so the order matters.
  • The first chunk creates the run (unless run.ulid names one); the others reuse it.
  • When a chunk fails after its retries, the later chunks of that project are not sent and the run is left open; a results file keeps them.
  • Uploads start once their report is recorded, attachmentConcurrency results at a time (1 to 8, default 2), and the run is closed after the uploads.

Every report, run creation, run close and attachment commit carries an Idempotency-Key, the same on each retry of that request. A retried report whose first attempt was recorded after all is replayed by Probara, never recorded twice. Running cypress run again is a new run, with every result recorded again.

The reporter uses Node’s built-in fetch, and has no proxy option of its own. With the plugin registered, the requests leave the process of the Node.js that started cypress:

Node.jsProxy support
22.21 or later, 24 or laterSet NODE_USE_ENV_PROXY=1 with HTTPS_PROXY (and NO_PROXY); fetch goes through it
22.12 to 22.20Not supported: fetch ignores HTTPS_PROXY and HTTP_PROXY
Terminal window
NODE_USE_ENV_PROXY=1 HTTPS_PROXY=http://proxy.example.com:8080 npx cypress run

Node added fetch support for NODE_USE_ENV_PROXY in 22.21.0 and 24.0.0 (Node’s docs). Cypress reads HTTPS_PROXY and NO_PROXY for the browser’s traffic too (Cypress’s proxy configuration): put the hosts your tests reach directly in NO_PROXY. On older Node versions, upgrade Node or allow the base URL through the firewall. Behind a proxy, register the plugin: without it, the requests leave Cypress’s own process instead.

For a self-hosted Probara behind a private certificate authority, give Node the CA certificate (PEM) when it starts:

Terminal window
NODE_EXTRA_CA_CERTS=/etc/ssl/certs/company-ca.pem npx cypress run

Node reads NODE_EXTRA_CA_CERTS once at startup, so set it in the environment of the step. On Node 22.19 and later, NODE_USE_SYSTEM_CA=1 trusts the operating system’s certificate store instead. There is no option to turn TLS verification off.

cypress open reports nothing. Cypress builds the reporter of its config only during cypress run: the app shows its own command log instead. A cypress open session with the reporter, the plugin and the support file registered runs its tests as usual and creates no run in Probara. To report the specs you are working on, run them with cypress run --spec:

Terminal window
PROBARA_API_TOKEN=… PROBARA_PROJECT=SHOP npx cypress run --spec 'cypress/e2e/cart.cy.js'

To collect a few local cypress run commands in one run, create it once and pass its ULID to each; a run the reporter did not create is never closed by it:

Terminal window
PROBARA_RUN_ULID=$(npx @probara/cli run create --run-name "Cart rework")
export PROBARA_RUN_ULID
npx cypress run --spec 'cypress/e2e/cart.cy.js'
npx cypress run --spec 'cypress/e2e/checkout.cy.js'
npx @probara/cli run close

Related: Get started · Results and retries · Troubleshooting · Source: configuration.md, network.md, watch.md