Cypress tests often need to interact with different application environments (dev, staging, production). The most straightforward way to manage this is by passing environment variables to your Cypress tests.

Let’s see Cypress in action, reading environment variables to configure its behavior. Imagine we have a Cypress test that needs to hit a specific API endpoint, which changes depending on the environment.

// cypress/e2e/api.cy.js
describe('API Tests', () => {
  it('fetches data from the correct environment', () => {
    // Access the environment variable
    const apiUrl = Cypress.env('API_URL');
    cy.request(`${apiUrl}/users`).then((response) => {
      expect(response.status).to.eq(200);
      // Further assertions on response.body
    });
  });
});

Now, how do we set API_URL? There are several ways, each with its own use case.

Setting Environment Variables

1. Via cypress.env.json:

This is the simplest method for local development. Create a file named cypress.env.json in the root of your project.

// cypress/cypress.env.json
{
  "API_URL": "http://localhost:3000/api",
  "AUTH_TOKEN": "local_test_token_123"
}

When you run Cypress, it automatically loads this file. You can then access API_URL in your tests as shown above. This is great for keeping environment-specific settings out of your main cypress.config.js file, especially when those settings might be sensitive.

2. Via Command Line Arguments:

For CI/CD or quick overrides, you can pass variables directly when running Cypress.

CYPRESS_API_URL=https://staging.example.com/api npx cypress run

Or, if you’re using cypress.config.js and want to pass them during a local run:

npx cypress open --env API_URL=https://staging.example.com/api,AUTH_TOKEN=staging_token_456

Notice how multiple variables are comma-separated when using the --env flag. This is useful for temporary changes or for scripting specific test runs.

3. Via cypress.config.js:

You can also define default environment variables directly in your configuration file.

// cypress/cypress.config.js
const { defineConfig } = require('cypress');

module.exports = defineConfig({
  env: {
    API_URL: 'http://localhost:3000/api',
    AUTH_TOKEN: 'default_token',
    // Other environment variables can go here
  },
  e2e: {
    setupNodeEvents(on, config) {
      // implement node event listeners here
    },
  },
});

These variables are loaded first. If you then use cypress.env.json or command-line arguments, they will override these defaults. This provides a good fallback mechanism.

4. Via System Environment Variables:

Cypress also respects standard system environment variables. This is the most common method in CI/CD pipelines.

If you have a variable set in your shell:

export API_URL="https://prod.example.com/api"
npx cypress run

Cypress will automatically pick it up. This is ideal for production deployments where you don’t want to commit sensitive credentials or URLs to your repository. Your CI/CD platform will typically inject these variables into the build environment.

The Mental Model: How Cypress Loads Variables

Cypress loads environment variables in a specific order of precedence. Understanding this helps you debug and control which values are active:

  1. System Environment Variables: Variables set directly in your operating system’s environment (e.g., export VAR=value in bash, or system settings in Windows). These have the highest precedence.
  2. cypress.env.json: The file in your project root.
  3. cypress.config.js (env object): Variables defined within the env property of your cypress.config.js.

When you run Cypress, it merges these sources. If a variable is defined in multiple places, the one with the higher precedence wins. For example, a system environment variable API_URL will override an API_URL defined in cypress.env.json, which in turn overrides one defined in cypress.config.js.

This layering allows you to set broad defaults in cypress.config.js, specific overrides for local development in cypress.env.json, and production-ready values via system environment variables in CI.

The Cypress.env() command is your gateway to these variables within your test files. It’s a simple key-value lookup that provides the dynamic configuration your tests need to adapt to different deployment targets.

When you’re working with multiple environments, you’ll often want to dynamically select which environment configuration to use based on a command-line argument or a CI job name.

Want structured learning?

Take the full Cypress course →