Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteIn Cypress 15.10.0, read sensitive values with the asynchronous cy.env() command and expose only intentionally public values through Cypress.expose(). Configure values in cypress.config.js or cypress.config.ts, cypress.env.json, operating-system variables, the CLI, or setupNodeEvents. The older Cypress.env() API is deprecated in 15.10.0 and is removed in Cypress 16.0.
Choose the right API for each value
| API | Use it for | Access and visibility |
|---|---|---|
cy.env(['KEY']) |
Secrets such as passwords, tokens, and API keys | Asynchronous Cypress command; requests only the named keys. Keep the yielded value inside a .then() callback. |
Cypress.expose('key') |
Public values such as feature flags, API versions, and environment labels | Synchronous browser-context access. Treat the value as public: application code, third-party scripts, and browser extensions can access it. |
Cypress.env() |
Existing code being migrated | Deprecated in 15.10.0; removed in 16.0. Avoid it in new 15.10.0 tests. |
Cypress introduced cy.env() because the old API hydrated configured values into browser context, including values a test did not read. The new approach distinguishes explicitly requested secrets from deliberately exposed public data. See the Cypress environment and secrets guide, the cy.env() reference, and the Cypress.expose() reference.
As an Amazon Associate I earn from qualifying purchases.
Set environment values
Custom test values are configured separately from Cypress configuration options such as baseUrl. Values can be strings, numbers, booleans, or objects, depending on how they are supplied. Match key spelling and capitalization exactly.
In Cypress configuration
Put custom test values under the top-level env key. Read secrets from the process environment instead of writing them into source control:
#1 Best Overall
const { defineConfig } = require('cypress')
module.exports = defineConfig({
env: {
apiToken: process.env.API_TOKEN,
region: 'staging-west',
},
})
The equivalent configuration can be written in cypress.config.ts. Configuration-file env values are available to cy.env(); do not use the test configuration env block as a way to set values in Cypress 15.10.0.
With cypress.env.json
Create cypress.env.json in the project root:
{
"apiToken": "replace-with-local-token",
"region": "staging-west"
}
Its values override conflicting entries in the config file’s env block. If the file contains secrets, add it to .gitignore and do not commit it.
From operating-system variables
Set a variable whose name starts with CYPRESS_; Cypress strips the prefix and normalizes the remaining name for custom test values. Lowercase cypress_ is also accepted. For example, provide CYPRESS_API_TOKEN in the process environment and request the corresponding configured key in your test. Do not set CYPRESS_INTERNAL_ENV; it is reserved.
Rank #2
With the CLI
Pass comma-separated key=value pairs to --env:
npx cypress run --env host=staging.example,region=west
For nested objects or values containing delimiters, pass JSON as a string, following the Cypress CLI reference. Avoid putting production secrets on a command line: they may be visible in CI logs or process details. Use your CI platform’s protected secret or masked-variable feature instead.
In setupNodeEvents
Use the Node-side setupNodeEvents hook when values need to be assembled dynamically. Update the configuration’s env object and return the configuration as required by the setup flow:
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
config.env.apiToken = process.env.API_TOKEN
return config
},
},
})
For all accepted sources and configuration precedence, see the Cypress configuration reference.
Rank #3
Read secrets safely with cy.env()
cy.env() is read-only and asynchronous. Pass an array of key names, then use the result in the Cypress command chain:
cy.env(['apiToken']).then(({ apiToken }) => {
cy.request({
url: '/api/account',
headers: { Authorization: `Bearer ${apiToken}` },
}).its('status').should('eq', 200)
})
The command logs the requested key names, not their values. That protection ends when the value is yielded: the result is an ordinary JavaScript object, and later assertions, .its(), .invoke(), or failing chained commands can print secret values to the Command Log or console. Keep secrets inside the callback and pass them directly to the operation that needs them. To check presence without exposing the value in an assertion, derive and assert a boolean:
cy.env(['apiToken']).then(({ apiToken }) => {
const tokenExists = typeof apiToken === 'string' && apiToken.length > 0
expect(tokenExists, 'API token is configured').to.equal(true)
})
For the command’s behavior and security boundaries, consult the cy.env() reference.
Expose non-sensitive values with Cypress.expose()
Configure public browser-readable data with the top-level expose option, then read a value synchronously in a test:
const { defineConfig } = require('cypress')
module.exports = defineConfig({
expose: {
apiVersion: 'v2',
environmentLabel: 'staging',
},
})
const apiVersion = Cypress.expose('apiVersion')
expect(apiVersion).to.equal('v2')
Never place a password, token, or other credential in expose. Exposed values are available in browser context and should be treated as public. The option was added in 15.10.0; its current behavior is documented in the Cypress.expose() reference.
Recommended Free Tools
Do not confuse custom test values with configuration overrides
The CYPRESS_ prefix has two related but distinct uses. A prefixed variable can supply a custom test value, or it can override a Cypress configuration option. For example, CYPRESS_BASE_URL, CYPRESS_REPORTER, and viewport variables override Cypress settings; they are not simply custom keys to retrieve as test data. Consult the Cypress environment variables guide for naming and override behavior.
Best Value
Cypress Cloud recording credentials have a separate constraint: CYPRESS_RECORD_KEY and CYPRESS_PROJECT_ID must be available from the operating-system environment for recording. They cannot be supplied through cypress.env.json or the configuration file’s env block. In CI, store them as protected or masked secrets and ensure they reach the Cypress process. See the Cypress CI guide.
Migrate Cypress.env() in Cypress 15.10.0
- Search tests and plugins for every
Cypress.env()call. Classify each value as secret or public. - Change secret reads to
cy.env(['key'])and adapt callers to the asynchronous command chain. - Move values genuinely safe for browser access into
expose, then read them withCypress.expose('key'). - Check CLI flags and plugins for dependencies on the deprecated API.
- After migrating old calls, set
allowCypressEnv: falsein Cypress 15.10.0 to make remaining uses fail visibly. Remove this setting when upgrading to Cypress 16.0, where the option, likeCypress.env(), is removed.
For the version-specific change, use the Cypress migration guide. Cypress 15.10.0 behavior should not be confused with the Cypress 16.0 removal boundary.
Troubleshoot common problems
- A value is undefined: Confirm it is supplied through a supported source, the key spelling and capitalization match, and the correct config file or project root is in use. A value in
cypress.env.jsontakes precedence over a conflicting configenvvalue. - A Cypress configuration setting is not changing: Check that the variable is intended to override a Cypress option, such as
CYPRESS_BASE_URL, rather than be read as a custom test value. These are distinct uses of the prefix. - cy.env() returns nothing or code runs too early: Treat it as asynchronous and consume its result in
.then(); it is not a synchronous getter or a setter. - A secret appears in a log: Remove assertions or chained operations that operate on the secret itself. Keep it in the callback and assert only a derived boolean when checking presence.
- A recording key is ignored: Put
CYPRESS_RECORD_KEYandCYPRESS_PROJECT_IDin the OS environment available to the Cypress process, not the configenvblock orcypress.env.json. - An old call fails after upgrading: Replace
Cypress.env(); it is removed in Cypress 16.0. Also removeallowCypressEnvduring that upgrade because that option is removed too. - A secret reaches browser code: Remove it from
exposeand usecy.env()for the test operation that needs it. Keep local secret files out of version control and use CI secret storage.
Or skip the browser setup
If the task is capturing a website rather than wiring a Cypress test, ScreenshotNeo provides a website screenshot API and MCP server. A single GET request can return an image or PDF:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options. It accepts cookie banners and removes known consent platforms, newsletter popups, and chat widgets before capture; bot checks, blank pages, and failed loads are not billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots per month with no card, and paid plans start at $5 for 3,000.
Sign up for ScreenshotNeo’s free plan.
Frequently Asked Questions
Does cy.env() set an environment variable?
No. In Cypress 15.10.0, cy.env() reads configured values; it is read-only.
Can I use Cypress.env() in Cypress 15.10.0?
It is deprecated in 15.10.0. Migrate to cy.env() for sensitive values or Cypress.expose() for public values; Cypress.env() is removed in 16.0.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Free tools Windows power users keep installed
One-click scans. No signup required.




