{
  "doc": {
    "id": "app/configure/environment-variables",
    "title": "Environment variables and secrets in Cypress",
    "description": "Learn how to manage environment variables and secrets in Cypress. Understand when to use cy.env(), when to use Cypress.expose(), and how to safely pass values across environments.",
    "section": "app",
    "source_path": "/llm/markdown/app/configure/environment-variables.md",
    "version": "066c46e056f0f322a0670d2d3aa4e6adaebfe717",
    "updated_at": "2026-09-10T13:30:12.426Z",
    "headings": [
      {
        "id": "app/configure/environment-variables#environment-variables-secrets",
        "text": "Environment Variables & Secrets",
        "level": 1
      },
      {
        "id": "app/configure/environment-variables#secrets-and-sensitive-values",
        "text": "Secrets and sensitive values",
        "level": 2
      },
      {
        "id": "app/configure/environment-variables#handling-the-yielded-value-safely",
        "text": "Handling the yielded value safely",
        "level": 3
      },
      {
        "id": "app/configure/environment-variables#public-configuration-values",
        "text": "Public configuration values",
        "level": 2
      },
      {
        "id": "app/configure/environment-variables#set-environment-variables",
        "text": "Set environment variables",
        "level": 2
      },
      {
        "id": "app/configure/environment-variables#1-configuration-file",
        "text": "1. Configuration File",
        "level": 3
      },
      {
        "id": "app/configure/environment-variables#2-cypress-env-json",
        "text": "2. cypress.env.json",
        "level": 3
      },
      {
        "id": "app/configure/environment-variables#3-cypress-environment-variables",
        "text": "3. CYPRESS_* environment variables",
        "level": 3
      },
      {
        "id": "app/configure/environment-variables#4-env-cli-flag",
        "text": "4. --env CLI flag",
        "level": 3
      },
      {
        "id": "app/configure/environment-variables#5-setupnodeevents",
        "text": "5. setupNodeEvents",
        "level": 3
      },
      {
        "id": "app/configure/environment-variables#set-exposed-configuration",
        "text": "Set exposed configuration",
        "level": 2
      },
      {
        "id": "app/configure/environment-variables#1-configuration-file",
        "text": "1. Configuration file",
        "level": 3
      },
      {
        "id": "app/configure/environment-variables#2-expose-cli-flag",
        "text": "2. --expose CLI flag",
        "level": 3
      },
      {
        "id": "app/configure/environment-variables#migrate-from-cypress-env",
        "text": "Migrate from Cypress.env()",
        "level": 2
      },
      {
        "id": "app/configure/environment-variables#see-also",
        "text": "See also",
        "level": 2
      }
    ]
  },
  "chunks": [
    {
      "id": "app/configure/environment-variables#secrets-and-sensitive-values",
      "doc_id": "app/configure/environment-variables",
      "heading": "Secrets and sensitive values",
      "heading_level": 2,
      "content_markdown": "## Secrets and sensitive values\n\n**Use [`cy.env()`](/llm/markdown/api/commands/env.md)** for sensitive values like API keys, passwords, tokens, or credentials.\n\n`cy.env()` retrieves only the values you explicitly request, when you need them, and avoids exposing all environment variables in browser state. This provides privileged access that doesn't automatically serialize values into browser context.\n\n**Examples of secrets:**\n\n*   API keys\n*   Authentication tokens\n*   Passwords\n*   Database credentials\n*   Private service endpoints\n\n```\ncy.env(['apiKey']).then(({ apiKey }) => {\n  cy.request({\n    url: 'https://api.example.com/data',\n    headers: { Authorization: `Bearer ${apiKey}` },\n  })\n})\n```\n\nSee the [`cy.env()`](/llm/markdown/api/commands/env.md) command documentation for complete details.\n\n`cy.env()` logs the key names you ask for and never the values. That protection ends at the command boundary. The object `cy.env()` yields is an ordinary JavaScript object, and Cypress does not mask, redact, or track the values inside it. Assertions, [`.its()`](/llm/markdown/api/commands/its.md), [`.invoke()`](/llm/markdown/api/commands/invoke.md), and any chained command that fails can all print a value to the [Command Log](/llm/markdown/app/core-concepts/open-mode.md#Command-Log) and the [console output](/llm/markdown/app/core-concepts/open-mode.md#Console-output). What happens to a value after `cy.env()` yields it is up to you. See [Handling the yielded value safely](/llm/markdown/api/commands/env.md#Handling-the-yielded-value-safely).\n\n### Handling the yielded value safely\n\nKeep the value inside a `.then()` callback and pass it straight to the command that needs it. [`.then()`](/llm/markdown/api/commands/then.md) adds no entry to the Command Log.\n\nEvery assertion writes to the Command Log, and the entry contains the values being compared. Assertions accept no logging options, so you cannot suppress them. Assert on a boolean you derive from the value instead.\n\n**Incorrect Usage**\n\n```\ncy.env(['apiKey']).should('deep.include', { apiKey: 'secret-key-12345' })\n// ❌ Command Log: assert expected { apiKey: 'secret-key-12345' } to deep\n// include { apiKey: 'secret-key-12345' }\n```\n\n**Correct Usage**\n\n```\ncy.env(['apiKey']).then(({ apiKey }) => {\n  expect(Boolean(apiKey)).to.be.true\n})\n// ✅ Command Log: assert expected true to be true\n```\n",
      "section": "app",
      "anchors": [
        "secrets-and-sensitive-values"
      ],
      "path": "/llm/json/chunked/app/configure/environment-variables.json",
      "token_estimate": 385
    },
    {
      "id": "app/configure/environment-variables#handling-the-yielded-value-safely",
      "doc_id": "app/configure/environment-variables",
      "heading": "Handling the yielded value safely",
      "heading_level": 3,
      "content_markdown": "### Handling the yielded value safely\n\nKeep the value inside a `.then()` callback and pass it straight to the command that needs it. [`.then()`](/llm/markdown/api/commands/then.md) adds no entry to the Command Log.\n\nEvery assertion writes to the Command Log, and the entry contains the values being compared. Assertions accept no logging options, so you cannot suppress them. Assert on a boolean you derive from the value instead.\n\n**Incorrect Usage**\n\n```\ncy.env(['apiKey']).should('deep.include', { apiKey: 'secret-key-12345' })\n// ❌ Command Log: assert expected { apiKey: 'secret-key-12345' } to deep\n// include { apiKey: 'secret-key-12345' }\n```\n\n**Correct Usage**\n\n```\ncy.env(['apiKey']).then(({ apiKey }) => {\n  expect(Boolean(apiKey)).to.be.true\n})\n// ✅ Command Log: assert expected true to be true\n```\n",
      "section": "app",
      "anchors": [
        "handling-the-yielded-value-safely"
      ],
      "path": "/llm/json/chunked/app/configure/environment-variables.json",
      "token_estimate": 152
    },
    {
      "id": "app/configure/environment-variables#public-configuration-values",
      "doc_id": "app/configure/environment-variables",
      "heading": "Public configuration values",
      "heading_level": 2,
      "content_markdown": "## Public configuration values\n\n**Use [`Cypress.expose()`](/llm/markdown/api/cypress-api/expose.md)** for public, non-sensitive configuration values.\n\n`Cypress.expose()` provides synchronous access to configuration that is safe to expose in the browser context. Values are accessible to application code, third-party scripts, and browser extensions.\n\n**Examples of public configuration:**\n\n*   Feature flags\n*   API versions\n*   Plugin configuration\n*   Environment labels (staging, prod)\n*   Public service URLs\n\n```\nconst apiVersion = Cypress.expose('apiVersion') // Synchronous access\nconst featureFlag = Cypress.expose('featureFlag')\n\nif (featureFlag) {\n  cy.get(`[data-testid=\"feature-${apiVersion}\"]`).should('be.visible')\n}\n```\n\nSee the [`Cypress.expose()`](/llm/markdown/api/cypress-api/expose.md) API documentation for complete details.\n",
      "section": "app",
      "anchors": [
        "public-configuration-values"
      ],
      "path": "/llm/json/chunked/app/configure/environment-variables.json",
      "token_estimate": 113
    },
    {
      "id": "app/configure/environment-variables#set-environment-variables",
      "doc_id": "app/configure/environment-variables",
      "heading": "Set environment variables",
      "heading_level": 2,
      "content_markdown": "## Set environment variables\n\nEnvironment variables for `cy.env()` can be set using several methods:\n\n1.  **Cypress configuration file** - Set in the `env` key of your Cypress configuration\n2.  **`cypress.env.json` file** - Create a `cypress.env.json` file in your project root\n3.  **`CYPRESS_*` environment variables** - Set OS-level environment variables with `CYPRESS_` prefix\n4.  **`--env` CLI flag** - Pass environment variables via command line\n5.  **`setupNodeEvents`** - Set dynamically in the `setupNodeEvents` function\n\n### 1\\. Configuration File\n\nSet environment variables in your Cypress configuration file under the `env` key:\n\n*   cypress.config.js\n*   cypress.config.ts\n\n```\nconst { defineConfig } = require('cypress')\n\nmodule.exports = defineConfig({\n  env: {\n    apiUrl: 'https://api.example.com',\n    apiKey: process.env.API_KEY, // From OS environment\n  },\n})\n```\n\n```\nimport { defineConfig } from 'cypress'\n\nexport default defineConfig({\n  env: {\n    apiUrl: 'https://api.example.com',\n    apiKey: process.env.API_KEY, // From OS environment\n  },\n})\n```\n\n### 2\\. `cypress.env.json`\n\nCreate a `cypress.env.json` file in your project root. Values here override conflicting environment variables in your Cypress configuration.\n\n```\n{\n  \"host\": \"veronica.dev.local\",\n  \"api_server\": \"http://localhost:8888/api/v1/\"\n}\n```\n\n**Important**: Add `cypress.env.json` to `.gitignore` if it contains sensitive data.\n\n### 3\\. `CYPRESS_*` environment variables\n\nSet OS-level environment variables with the `CYPRESS_` or `cypress_` prefix:\n\n```\nexport CYPRESS_HOST=laura.dev.local\nexport cypress_api_server=http://localhost:8888/api/v1/\n```\n\nCypress automatically removes the leading `CYPRESS_` or `cypress_` prefix and normalizes the name.\n\nThe environment variable `CYPRESS_INTERNAL_ENV` is reserved and should not be set.\n\nSome `CYPRESS_`\\-prefixed variables are consumed by the Cypress CLI and Cypress Cloud rather than being treated as test environment variables. Most notably, [`CYPRESS_RECORD_KEY`](/llm/markdown/app/references/command-line.md#cypress-run-record-key-lt-record-key-gt) and [`CYPRESS_PROJECT_ID`](/llm/markdown/cloud/account-management/projects.md#Project-ID) are read directly from your operating system environment when recording to Cypress Cloud. They must be set as OS-level environment variables (as shown above) and **cannot** be supplied through `cypress.env.json` or the `env` block of your Cypress configuration.\n\n### 4\\. `--env` CLI flag\n\nPass environment variables via the command line. Multiple values must be separated by a comma, not a space. In some shells, like Windows PowerShell, you may need to surround the key/value pair with quotes.\n\n```\ncypress run --env host=kevin.dev.local,api_server=http://localhost:8888/api/v1\n```\n\nTo pass a complex value, such as an object with nested fields, provide it as a JSON string. This is also the way to include values that contain commas, spaces, or quotes, since those characters would otherwise be interpreted by the shell or as delimiters.\n\n```\ncypress run --env credentials='{\"apiKey\":\"secret-key-12345\",\"auth\":{\"user\":\"jane\",\"token\":\"abc123\"}}'\n```\n\nSee the [`--env`](/llm/markdown/app/references/command-line.md#cypress-run-env-lt-env-gt) command line reference for more details.\n\n### 5\\. setupNodeEvents\n\nSet environment variables dynamically in the `setupNodeEvents` function:\n\n*   cypress.config.js\n*   cypress.config.ts\n\n```\nconst { defineConfig } = require('cypress')\n\nmodule.exports = defineConfig({\n  // setupNodeEvents can be defined in either\n  // the e2e or component configuration\n  e2e: {\n    setupNodeEvents(on, config) {\n      export default defineConfig({\n        e2e: {\n          setupNodeEvents(on, config) {\n            config.env.apiKey = process.env.API_KEY\n            return config\n          },\n        },\n      })\n    },\n  },\n})\n```\n\n```\nimport { defineConfig } from 'cypress'\n\nexport default defineConfig({\n  // setupNodeEvents can be defined in either\n  // the e2e or component configuration\n  e2e: {\n    setupNodeEvents(on, config) {\n      export default defineConfig({\n        e2e: {\n          setupNodeEvents(on, config) {\n            config.env.apiKey = process.env.API_KEY\n            return config\n          },\n        },\n      })\n    },\n  },\n})\n```\n",
      "section": "app",
      "anchors": [
        "set-environment-variables"
      ],
      "path": "/llm/json/chunked/app/configure/environment-variables.json",
      "token_estimate": 668
    },
    {
      "id": "app/configure/environment-variables#1-configuration-file",
      "doc_id": "app/configure/environment-variables",
      "heading": "1. Configuration File",
      "heading_level": 3,
      "content_markdown": "### 1\\. Configuration File\n\nSet environment variables in your Cypress configuration file under the `env` key:\n\n*   cypress.config.js\n*   cypress.config.ts\n\n```\nconst { defineConfig } = require('cypress')\n\nmodule.exports = defineConfig({\n  env: {\n    apiUrl: 'https://api.example.com',\n    apiKey: process.env.API_KEY, // From OS environment\n  },\n})\n```\n\n```\nimport { defineConfig } from 'cypress'\n\nexport default defineConfig({\n  env: {\n    apiUrl: 'https://api.example.com',\n    apiKey: process.env.API_KEY, // From OS environment\n  },\n})\n```\n",
      "section": "app",
      "anchors": [
        "1-configuration-file"
      ],
      "path": "/llm/json/chunked/app/configure/environment-variables.json",
      "token_estimate": 88
    },
    {
      "id": "app/configure/environment-variables#2-cypress-env-json",
      "doc_id": "app/configure/environment-variables",
      "heading": "2. cypress.env.json",
      "heading_level": 3,
      "content_markdown": "### 2\\. `cypress.env.json`\n\nCreate a `cypress.env.json` file in your project root. Values here override conflicting environment variables in your Cypress configuration.\n\n```\n{\n  \"host\": \"veronica.dev.local\",\n  \"api_server\": \"http://localhost:8888/api/v1/\"\n}\n```\n\n**Important**: Add `cypress.env.json` to `.gitignore` if it contains sensitive data.\n",
      "section": "app",
      "anchors": [
        "2-cypress-env-json"
      ],
      "path": "/llm/json/chunked/app/configure/environment-variables.json",
      "token_estimate": 52
    },
    {
      "id": "app/configure/environment-variables#3-cypress-environment-variables",
      "doc_id": "app/configure/environment-variables",
      "heading": "3. CYPRESS_* environment variables",
      "heading_level": 3,
      "content_markdown": "### 3\\. `CYPRESS_*` environment variables\n\nSet OS-level environment variables with the `CYPRESS_` or `cypress_` prefix:\n\n```\nexport CYPRESS_HOST=laura.dev.local\nexport cypress_api_server=http://localhost:8888/api/v1/\n```\n\nCypress automatically removes the leading `CYPRESS_` or `cypress_` prefix and normalizes the name.\n\nThe environment variable `CYPRESS_INTERNAL_ENV` is reserved and should not be set.\n\nSome `CYPRESS_`\\-prefixed variables are consumed by the Cypress CLI and Cypress Cloud rather than being treated as test environment variables. Most notably, [`CYPRESS_RECORD_KEY`](/llm/markdown/app/references/command-line.md#cypress-run-record-key-lt-record-key-gt) and [`CYPRESS_PROJECT_ID`](/llm/markdown/cloud/account-management/projects.md#Project-ID) are read directly from your operating system environment when recording to Cypress Cloud. They must be set as OS-level environment variables (as shown above) and **cannot** be supplied through `cypress.env.json` or the `env` block of your Cypress configuration.\n",
      "section": "app",
      "anchors": [
        "3-cypress-environment-variables"
      ],
      "path": "/llm/json/chunked/app/configure/environment-variables.json",
      "token_estimate": 144
    },
    {
      "id": "app/configure/environment-variables#4-env-cli-flag",
      "doc_id": "app/configure/environment-variables",
      "heading": "4. --env CLI flag",
      "heading_level": 3,
      "content_markdown": "### 4\\. `--env` CLI flag\n\nPass environment variables via the command line. Multiple values must be separated by a comma, not a space. In some shells, like Windows PowerShell, you may need to surround the key/value pair with quotes.\n\n```\ncypress run --env host=kevin.dev.local,api_server=http://localhost:8888/api/v1\n```\n\nTo pass a complex value, such as an object with nested fields, provide it as a JSON string. This is also the way to include values that contain commas, spaces, or quotes, since those characters would otherwise be interpreted by the shell or as delimiters.\n\n```\ncypress run --env credentials='{\"apiKey\":\"secret-key-12345\",\"auth\":{\"user\":\"jane\",\"token\":\"abc123\"}}'\n```\n\nSee the [`--env`](/llm/markdown/app/references/command-line.md#cypress-run-env-lt-env-gt) command line reference for more details.\n",
      "section": "app",
      "anchors": [
        "4-env-cli-flag"
      ],
      "path": "/llm/json/chunked/app/configure/environment-variables.json",
      "token_estimate": 140
    },
    {
      "id": "app/configure/environment-variables#5-setupnodeevents",
      "doc_id": "app/configure/environment-variables",
      "heading": "5. setupNodeEvents",
      "heading_level": 3,
      "content_markdown": "### 5\\. setupNodeEvents\n\nSet environment variables dynamically in the `setupNodeEvents` function:\n\n*   cypress.config.js\n*   cypress.config.ts\n\n```\nconst { defineConfig } = require('cypress')\n\nmodule.exports = defineConfig({\n  // setupNodeEvents can be defined in either\n  // the e2e or component configuration\n  e2e: {\n    setupNodeEvents(on, config) {\n      export default defineConfig({\n        e2e: {\n          setupNodeEvents(on, config) {\n            config.env.apiKey = process.env.API_KEY\n            return config\n          },\n        },\n      })\n    },\n  },\n})\n```\n\n```\nimport { defineConfig } from 'cypress'\n\nexport default defineConfig({\n  // setupNodeEvents can be defined in either\n  // the e2e or component configuration\n  e2e: {\n    setupNodeEvents(on, config) {\n      export default defineConfig({\n        e2e: {\n          setupNodeEvents(on, config) {\n            config.env.apiKey = process.env.API_KEY\n            return config\n          },\n        },\n      })\n    },\n  },\n})\n```\n",
      "section": "app",
      "anchors": [
        "5-setupnodeevents"
      ],
      "path": "/llm/json/chunked/app/configure/environment-variables.json",
      "token_estimate": 148
    },
    {
      "id": "app/configure/environment-variables#set-exposed-configuration",
      "doc_id": "app/configure/environment-variables",
      "heading": "Set exposed configuration",
      "heading_level": 2,
      "content_markdown": "## Set exposed configuration\n\nExposed configuration for `Cypress.expose()` can be set via:\n\n1.  **Cypress configuration file** - Set in the `expose` key of your Cypress configuration\n2.  **`--expose` CLI flag** - Pass exposed configuration via command line\n\n### 1\\. Configuration file\n\nSet exposed configuration in your Cypress configuration file under the `expose` key:\n\n*   cypress.config.js\n*   cypress.config.ts\n\n```\nconst { defineConfig } = require('cypress')\n\nmodule.exports = defineConfig({\n  expose: {\n    apiVersion: 'v2',\n    featureFlag: true,\n    environment: 'staging',\n  },\n})\n```\n\n```\nimport { defineConfig } from 'cypress'\n\nexport default defineConfig({\n  expose: {\n    apiVersion: 'v2',\n    featureFlag: true,\n    environment: 'staging',\n  },\n})\n```\n\n### 2\\. `--expose` CLI flag\n\nPass exposed configuration via the command line:\n\n```\ncypress run --expose apiVersion=v2,featureFlag=true\n```\n\nSee the [`Cypress.expose()`](/llm/markdown/api/cypress-api/expose.md) API documentation for complete details on setting exposed configuration.\n",
      "section": "app",
      "anchors": [
        "set-exposed-configuration"
      ],
      "path": "/llm/json/chunked/app/configure/environment-variables.json",
      "token_estimate": 172
    },
    {
      "id": "app/configure/environment-variables#1-configuration-file",
      "doc_id": "app/configure/environment-variables",
      "heading": "1. Configuration file",
      "heading_level": 3,
      "content_markdown": "### 1\\. Configuration file\n\nSet exposed configuration in your Cypress configuration file under the `expose` key:\n\n*   cypress.config.js\n*   cypress.config.ts\n\n```\nconst { defineConfig } = require('cypress')\n\nmodule.exports = defineConfig({\n  expose: {\n    apiVersion: 'v2',\n    featureFlag: true,\n    environment: 'staging',\n  },\n})\n```\n\n```\nimport { defineConfig } from 'cypress'\n\nexport default defineConfig({\n  expose: {\n    apiVersion: 'v2',\n    featureFlag: true,\n    environment: 'staging',\n  },\n})\n```\n",
      "section": "app",
      "anchors": [
        "1-configuration-file"
      ],
      "path": "/llm/json/chunked/app/configure/environment-variables.json",
      "token_estimate": 83
    },
    {
      "id": "app/configure/environment-variables#2-expose-cli-flag",
      "doc_id": "app/configure/environment-variables",
      "heading": "2. --expose CLI flag",
      "heading_level": 3,
      "content_markdown": "### 2\\. `--expose` CLI flag\n\nPass exposed configuration via the command line:\n\n```\ncypress run --expose apiVersion=v2,featureFlag=true\n```\n\nSee the [`Cypress.expose()`](/llm/markdown/api/cypress-api/expose.md) API documentation for complete details on setting exposed configuration.\n",
      "section": "app",
      "anchors": [
        "2-expose-cli-flag"
      ],
      "path": "/llm/json/chunked/app/configure/environment-variables.json",
      "token_estimate": 40
    },
    {
      "id": "app/configure/environment-variables#migrate-from-cypress-env",
      "doc_id": "app/configure/environment-variables",
      "heading": "Migrate from Cypress.env()",
      "heading_level": 2,
      "content_markdown": "## Migrate from Cypress.env()\n\n`Cypress.env()` was removed in Cypress 16.0. If your tests still call it, migrate each value to the appropriate modern API:\n\n*   **Sensitive values** → [`cy.env()`](/llm/markdown/api/commands/env.md)\n*   **Public configuration** → [`Cypress.expose()`](/llm/markdown/api/cypress-api/expose.md)\n\nSee the [Migration Guide](/llm/markdown/app/references/migration-guide.md#Migrating-away-from-Cypressenv) for detailed migration instructions.\n",
      "section": "app",
      "anchors": [
        "migrate-from-cypress-env"
      ],
      "path": "/llm/json/chunked/app/configure/environment-variables.json",
      "token_estimate": 56
    }
  ]
}