{
  "doc": {
    "id": "api/commands/env",
    "title": "cy.env()",
    "description": "Securely read environment variables in Cypress tests using cy.env(). Learn syntax, examples, security benefits, and how to migrate from Cypress.env().",
    "section": "api",
    "source_path": "/llm/markdown/api/commands/env.md",
    "version": "29f95bf8bb06f320986f3749f5bf09a35a409eab",
    "updated_at": "2026-09-04T10:49:54.630Z",
    "headings": [
      {
        "id": "api/commands/env#env",
        "text": "env",
        "level": 1
      },
      {
        "id": "api/commands/env#syntax",
        "text": "Syntax",
        "level": 2
      },
      {
        "id": "api/commands/env#usage",
        "text": "Usage",
        "level": 3
      },
      {
        "id": "api/commands/env#arguments",
        "text": "Arguments",
        "level": 3
      },
      {
        "id": "api/commands/env#yields",
        "text": "Yields",
        "level": 3
      },
      {
        "id": "api/commands/env#examples",
        "text": "Examples",
        "level": 2
      },
      {
        "id": "api/commands/env#single-variable",
        "text": "Single Variable",
        "level": 3
      },
      {
        "id": "api/commands/env#multiple-variables",
        "text": "Multiple Variables",
        "level": 3
      },
      {
        "id": "api/commands/env#use-environment-variables-across-tests",
        "text": "Use environment variables across tests",
        "level": 3
      },
      {
        "id": "api/commands/env#handle-required-vs-optional-variables",
        "text": "Handle required vs optional variables",
        "level": 3
      },
      {
        "id": "api/commands/env#chaining-with-other-commands",
        "text": "Chaining with other commands",
        "level": 3
      },
      {
        "id": "api/commands/env#use-cy-env-in-custom-commands",
        "text": "Use cy.env in custom commands",
        "level": 3
      },
      {
        "id": "api/commands/env#suppress-command-logging",
        "text": "Suppress command logging",
        "level": 3
      },
      {
        "id": "api/commands/env#handling-the-yielded-value-safely",
        "text": "Handling the yielded value safely",
        "level": 2
      },
      {
        "id": "api/commands/env#assert-on-a-derived-value-not-on-the-secret",
        "text": "Assert on a derived value, not on the secret",
        "level": 3
      },
      {
        "id": "api/commands/env#avoid-its-and-invoke-on-the-yielded-object",
        "text": "Avoid .its() and .invoke() on the yielded object",
        "level": 3
      },
      {
        "id": "api/commands/env#keep-the-value-out-of-downstream-command-logs",
        "text": "Keep the value out of downstream command logs",
        "level": 3
      },
      {
        "id": "api/commands/env#why-use-cy-env",
        "text": "Why use cy.env()?",
        "level": 2
      },
      {
        "id": "api/commands/env#secure-access-to-sensitive-values",
        "text": "Secure access to sensitive values",
        "level": 3
      },
      {
        "id": "api/commands/env#when-to-use-cy-env-vs-cypress-expose",
        "text": "When to use cy.env() vs Cypress.expose()",
        "level": 3
      },
      {
        "id": "api/commands/env#use-cypress-expose-for-public-configuration",
        "text": "Use Cypress.expose() for public configuration",
        "level": 4
      },
      {
        "id": "api/commands/env#use-cy-env-for-sensitive-or-secret-values",
        "text": "Use cy.env() for sensitive or secret values",
        "level": 4
      },
      {
        "id": "api/commands/env#migrate-from-cypress-env",
        "text": "Migrate from Cypress.env()",
        "level": 2
      },
      {
        "id": "api/commands/env#notes",
        "text": "Notes",
        "level": 2
      },
      {
        "id": "api/commands/env#read-only-behavior",
        "text": "Read-only behavior",
        "level": 3
      },
      {
        "id": "api/commands/env#test-configuration-overrides",
        "text": "Test configuration overrides",
        "level": 3
      },
      {
        "id": "api/commands/env#case-sensitivity",
        "text": "Case sensitivity",
        "level": 3
      },
      {
        "id": "api/commands/env#history",
        "text": "History",
        "level": 2
      },
      {
        "id": "api/commands/env#see-also",
        "text": "See also",
        "level": 2
      }
    ]
  },
  "chunks": [
    {
      "id": "api/commands/env#syntax",
      "doc_id": "api/commands/env",
      "heading": "Syntax",
      "heading_level": 2,
      "content_markdown": "## Syntax\n\n```\ncy.env(keys)\ncy.env(keys, options)\n```\n\n### Usage\n\n**Correct Usage**\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: 'secret-key-12345',\n  },\n  expose: {\n    environment: 'staging', // Public configuration value\n  },\n})\n```\n\n```\nimport { defineConfig } from 'cypress'\n\nexport default defineConfig({\n  env: {\n    apiUrl: 'https://api.example.com',\n    apiKey: 'secret-key-12345',\n  },\n  expose: {\n    environment: 'staging', // Public configuration value\n  },\n})\n```\n\n```\n// Get a single environment variable\ncy.env(['apiUrl']).then(({ apiUrl }) => {\n  cy.request(`${apiUrl}/users`).its('status').should('eq', 200)\n})\n\n// Get multiple environment variables\ncy.env(['apiUrl', 'apiKey']).then(({ apiUrl, apiKey }) => {\n  cy.request({\n    url: `${apiUrl}/users`,\n    headers: { Authorization: `Bearer ${apiKey}` },\n  })\n    .its('status')\n    .should('eq', 200)\n})\n\n// With options\ncy.env(['apiUrl'], { log: false }).then(({ apiUrl }) => {\n  // Use apiUrl\n})\n```\n\n### Arguments\n\n**keys _(String\\[\\])_**\n\nAn array of environment variable keys to retrieve from Cypress. These environment variables can be set via any of the methods described in the [Environment Variables & Secrets](/llm/markdown/app/guides/environment-variables.md) guide.\n\nEnvironment variables cannot be set using [test configuration](/llm/markdown/app/references/configuration.md#Test-Configuration).\n\nIf a variable is not defined, its value will return `undefined` in the returned object.\n\n**options _(Object)_**\n\nPass an options object to change the default behavior of `cy.env()`.\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `log` | `true` | Displays the command in the [Command log](/llm/markdown/app/core-concepts/open-mode.md#Command-Log). **Only variable names are logged, never values.** |\n| `timeout` | 4000 | Time to wait for `cy.env()` to resolve before timing out. |\n\n### Yields\n\n`cy.env()` yields an object with the values found for the environment variable keys requested.\n\n```\ncy.env(['apiUrl', 'apiKey']).then((env) => {\n  // env = { apiUrl: 'https://api.example.com', apiKey: 'secret-key-12345' }\n})\n```\n",
      "section": "api",
      "anchors": [
        "syntax"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 373
    },
    {
      "id": "api/commands/env#usage",
      "doc_id": "api/commands/env",
      "heading": "Usage",
      "heading_level": 3,
      "content_markdown": "### Usage\n\n**Correct Usage**\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: 'secret-key-12345',\n  },\n  expose: {\n    environment: 'staging', // Public configuration value\n  },\n})\n```\n\n```\nimport { defineConfig } from 'cypress'\n\nexport default defineConfig({\n  env: {\n    apiUrl: 'https://api.example.com',\n    apiKey: 'secret-key-12345',\n  },\n  expose: {\n    environment: 'staging', // Public configuration value\n  },\n})\n```\n\n```\n// Get a single environment variable\ncy.env(['apiUrl']).then(({ apiUrl }) => {\n  cy.request(`${apiUrl}/users`).its('status').should('eq', 200)\n})\n\n// Get multiple environment variables\ncy.env(['apiUrl', 'apiKey']).then(({ apiUrl, apiKey }) => {\n  cy.request({\n    url: `${apiUrl}/users`,\n    headers: { Authorization: `Bearer ${apiKey}` },\n  })\n    .its('status')\n    .should('eq', 200)\n})\n\n// With options\ncy.env(['apiUrl'], { log: false }).then(({ apiUrl }) => {\n  // Use apiUrl\n})\n```\n",
      "section": "api",
      "anchors": [
        "usage"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 163
    },
    {
      "id": "api/commands/env#arguments",
      "doc_id": "api/commands/env",
      "heading": "Arguments",
      "heading_level": 3,
      "content_markdown": "### Arguments\n\n**keys _(String\\[\\])_**\n\nAn array of environment variable keys to retrieve from Cypress. These environment variables can be set via any of the methods described in the [Environment Variables & Secrets](/llm/markdown/app/guides/environment-variables.md) guide.\n\nEnvironment variables cannot be set using [test configuration](/llm/markdown/app/references/configuration.md#Test-Configuration).\n\nIf a variable is not defined, its value will return `undefined` in the returned object.\n\n**options _(Object)_**\n\nPass an options object to change the default behavior of `cy.env()`.\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `log` | `true` | Displays the command in the [Command log](/llm/markdown/app/core-concepts/open-mode.md#Command-Log). **Only variable names are logged, never values.** |\n| `timeout` | 4000 | Time to wait for `cy.env()` to resolve before timing out. |\n",
      "section": "api",
      "anchors": [
        "arguments"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 159
    },
    {
      "id": "api/commands/env#yields",
      "doc_id": "api/commands/env",
      "heading": "Yields",
      "heading_level": 3,
      "content_markdown": "### Yields\n\n`cy.env()` yields an object with the values found for the environment variable keys requested.\n\n```\ncy.env(['apiUrl', 'apiKey']).then((env) => {\n  // env = { apiUrl: 'https://api.example.com', apiKey: 'secret-key-12345' }\n})\n```\n",
      "section": "api",
      "anchors": [
        "yields"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 43
    },
    {
      "id": "api/commands/env#examples",
      "doc_id": "api/commands/env",
      "heading": "Examples",
      "heading_level": 2,
      "content_markdown": "## Examples\n\n### Single Variable\n\nGet a single environment variable:\n\n```\ncy.env(['apiUrl']).then(({ apiUrl }) => {\n  cy.visit(apiUrl)\n})\n```\n\n### Multiple Variables\n\nGet multiple environment variables at once:\n\n```\ncy.env(['apiUrl', 'apiKey', 'timeout']).then(({ apiUrl, apiKey, timeout }) => {\n  cy.request({\n    url: `${apiUrl}/users`,\n    headers: { Authorization: `Bearer ${apiKey}` },\n    timeout: timeout || 5000,\n  })\n})\n```\n\n### Use environment variables across tests\n\nStore environment variables for use across multiple tests by using a `before()` hook:\n\n```\ndescribe('API tests', () => {\n  let apiBaseUrl\n\n  before(() => {\n    cy.env(['apiBaseUrl']).then(({ apiBaseUrl: url }) => {\n      apiBaseUrl = url\n    })\n  })\n\n  it('can make requests', () => {\n    cy.request(`${apiBaseUrl}/users`).its('status').should('eq', 200)\n  })\n})\n```\n\n### Handle required vs optional variables\n\nVariables that are not set will be `undefined`:\n\n```\ncy.env(['requiredVar', 'optionalVar']).then(({ requiredVar, optionalVar }) => {\n  if (requiredVar === undefined) {\n    throw new Error('requiredVar must be set in Cypress configuration')\n  }\n\n  // Use optionalVar only if it's defined\n  if (optionalVar) {\n    // Use optionalVar\n  }\n})\n```\n\n### Chaining with other commands\n\n```\ncy.env(['baseUrl']).then(({ baseUrl }) => {\n  cy.visit(baseUrl)\n  cy.get('h1').should('be.visible')\n})\n```\n\n### Use cy.env in custom commands\n\nCreate custom commands that use `cy.env()`:\n\n*   cypress/support/commands.js\n*   cypress/support/commands.ts\n\n```\n// cypress/support/commands.js\nCypress.Commands.add('apiRequest', (endpoint, options = {}) => {\n  cy.env(['apiUrl', 'apiKey']).then(({ apiUrl, apiKey }) => {\n    cy.request({\n      url: `${apiUrl}${endpoint}`,\n      headers: {\n        Authorization: `Bearer ${apiKey}`,\n        ...options.headers,\n      },\n      ...options,\n    })\n  })\n})\n\n// In your test\ncy.apiRequest('/users').its('status').should('eq', 200)\n```\n\n```\ndeclare global {\n  namespace Cypress {\n    interface Chainable {\n      apiRequest(\n        endpoint: string,\n        options?: Partial<Cypress.RequestOptions>\n      ): Chainable<Cypress.Response<any>>\n    }\n  }\n}\n\n// cypress/support/commands.js\nCypress.Commands.add('apiRequest', (endpoint, options = {}) => {\n  cy.env(['apiUrl', 'apiKey']).then(({ apiUrl, apiKey }) => {\n    cy.request({\n      url: `${apiUrl}${endpoint}`,\n      headers: {\n        Authorization: `Bearer ${apiKey}`,\n        ...options.headers,\n      },\n      ...options,\n    })\n  })\n})\n\n// In your test\ncy.apiRequest('/users').its('status').should('eq', 200)\n```\n\n### Suppress command logging\n\nHide the `cy.env()` entry from the Command Log. Because `cy.env()` logs key names and never values, use this option when you don't want the key names visible in the Command Log:\n\n```\ncy.env(['acmeMigrationKey'], { log: false }).then(({ acmeMigrationKey }) => {\n  // The command and the key name don't appear in the Command Log\n})\n```\n",
      "section": "api",
      "anchors": [
        "examples"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 460
    },
    {
      "id": "api/commands/env#multiple-variables",
      "doc_id": "api/commands/env",
      "heading": "Multiple Variables",
      "heading_level": 3,
      "content_markdown": "### Multiple Variables\n\nGet multiple environment variables at once:\n\n```\ncy.env(['apiUrl', 'apiKey', 'timeout']).then(({ apiUrl, apiKey, timeout }) => {\n  cy.request({\n    url: `${apiUrl}/users`,\n    headers: { Authorization: `Bearer ${apiKey}` },\n    timeout: timeout || 5000,\n  })\n})\n```\n",
      "section": "api",
      "anchors": [
        "multiple-variables"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 47
    },
    {
      "id": "api/commands/env#use-environment-variables-across-tests",
      "doc_id": "api/commands/env",
      "heading": "Use environment variables across tests",
      "heading_level": 3,
      "content_markdown": "### Use environment variables across tests\n\nStore environment variables for use across multiple tests by using a `before()` hook:\n\n```\ndescribe('API tests', () => {\n  let apiBaseUrl\n\n  before(() => {\n    cy.env(['apiBaseUrl']).then(({ apiBaseUrl: url }) => {\n      apiBaseUrl = url\n    })\n  })\n\n  it('can make requests', () => {\n    cy.request(`${apiBaseUrl}/users`).its('status').should('eq', 200)\n  })\n})\n```\n",
      "section": "api",
      "anchors": [
        "use-environment-variables-across-tests"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 69
    },
    {
      "id": "api/commands/env#handle-required-vs-optional-variables",
      "doc_id": "api/commands/env",
      "heading": "Handle required vs optional variables",
      "heading_level": 3,
      "content_markdown": "### Handle required vs optional variables\n\nVariables that are not set will be `undefined`:\n\n```\ncy.env(['requiredVar', 'optionalVar']).then(({ requiredVar, optionalVar }) => {\n  if (requiredVar === undefined) {\n    throw new Error('requiredVar must be set in Cypress configuration')\n  }\n\n  // Use optionalVar only if it's defined\n  if (optionalVar) {\n    // Use optionalVar\n  }\n})\n```\n",
      "section": "api",
      "anchors": [
        "handle-required-vs-optional-variables"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 71
    },
    {
      "id": "api/commands/env#use-cy-env-in-custom-commands",
      "doc_id": "api/commands/env",
      "heading": "Use cy.env in custom commands",
      "heading_level": 3,
      "content_markdown": "### Use cy.env in custom commands\n\nCreate custom commands that use `cy.env()`:\n\n*   cypress/support/commands.js\n*   cypress/support/commands.ts\n\n```\n// cypress/support/commands.js\nCypress.Commands.add('apiRequest', (endpoint, options = {}) => {\n  cy.env(['apiUrl', 'apiKey']).then(({ apiUrl, apiKey }) => {\n    cy.request({\n      url: `${apiUrl}${endpoint}`,\n      headers: {\n        Authorization: `Bearer ${apiKey}`,\n        ...options.headers,\n      },\n      ...options,\n    })\n  })\n})\n\n// In your test\ncy.apiRequest('/users').its('status').should('eq', 200)\n```\n\n```\ndeclare global {\n  namespace Cypress {\n    interface Chainable {\n      apiRequest(\n        endpoint: string,\n        options?: Partial<Cypress.RequestOptions>\n      ): Chainable<Cypress.Response<any>>\n    }\n  }\n}\n\n// cypress/support/commands.js\nCypress.Commands.add('apiRequest', (endpoint, options = {}) => {\n  cy.env(['apiUrl', 'apiKey']).then(({ apiUrl, apiKey }) => {\n    cy.request({\n      url: `${apiUrl}${endpoint}`,\n      headers: {\n        Authorization: `Bearer ${apiKey}`,\n        ...options.headers,\n      },\n      ...options,\n    })\n  })\n})\n\n// In your test\ncy.apiRequest('/users').its('status').should('eq', 200)\n```\n",
      "section": "api",
      "anchors": [
        "use-cy-env-in-custom-commands"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 148
    },
    {
      "id": "api/commands/env#suppress-command-logging",
      "doc_id": "api/commands/env",
      "heading": "Suppress command logging",
      "heading_level": 3,
      "content_markdown": "### Suppress command logging\n\nHide the `cy.env()` entry from the Command Log. Because `cy.env()` logs key names and never values, use this option when you don't want the key names visible in the Command Log:\n\n```\ncy.env(['acmeMigrationKey'], { log: false }).then(({ acmeMigrationKey }) => {\n  // The command and the key name don't appear in the Command Log\n})\n```\n",
      "section": "api",
      "anchors": [
        "suppress-command-logging"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 80
    },
    {
      "id": "api/commands/env#handling-the-yielded-value-safely",
      "doc_id": "api/commands/env",
      "heading": "Handling the yielded value safely",
      "heading_level": 2,
      "content_markdown": "## Handling the yielded value safely\n\n`cy.env()` logs the key names you ask for and never the values. That guarantee stops the moment the command yields. The object you receive is an ordinary JavaScript object, and Cypress does not mask, redact, or track the values inside it.\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) and [`.spread()`](/llm/markdown/api/commands/spread.md) add no entry to the Command Log, so the value stays out of it.\n\n### Assert on a derived value, not on the secret\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\nCalling `expect()` inside a `.then()` callback still creates an assertion entry, so a `.then()` callback alone is not enough. What you assert on is what matters.\n\n### Avoid .its() and .invoke() on the yielded object\n\n[`.its()`](/llm/markdown/api/commands/its.md) and [`.invoke()`](/llm/markdown/api/commands/invoke.md) both add the subject they were applied to and the value they yield to the console output, so `cy.env(['apiKey']).its('apiKey')` prints the environment variable value twice. Read the property inside a `.then()` callback instead.\n\n**Incorrect Usage**\n\n```\n// ❌ Prints the environment variable value to the console output twice\ncy.env(['apiKey']).its('apiKey')\n```\n\n**Correct Usage**\n\n```\ncy.env(['apiKey']).then(({ apiKey }) => {\n  // ✅ Use apiKey here\n})\n```\n\n### Keep the value out of downstream command logs\n\nCommands that accept a `log` option, such as [`cy.request()`](/llm/markdown/api/commands/request.md) and [`.type()`](/llm/markdown/api/commands/type.md), leave their entry out of the Command Log when you pass `{ log: false }`. Use it on any command you hand the value to:\n\n```\ncy.env(['apiKey']).then(({ apiKey }) => {\n  cy.request({\n    url: 'https://api.example.com/users',\n    headers: { Authorization: `Bearer ${apiKey}` },\n    log: false,\n  })\n\n  cy.get('[data-testid=\"token-field\"]').type(apiKey, { log: false })\n})\n```\n\n`{ log: false }` hides the entry from the Command Log. It does not redact the value, and it has no effect on assertions.\n",
      "section": "api",
      "anchors": [
        "handling-the-yielded-value-safely"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 495
    },
    {
      "id": "api/commands/env#assert-on-a-derived-value-not-on-the-secret",
      "doc_id": "api/commands/env",
      "heading": "Assert on a derived value, not on the secret",
      "heading_level": 3,
      "content_markdown": "### Assert on a derived value, not on the secret\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\nCalling `expect()` inside a `.then()` callback still creates an assertion entry, so a `.then()` callback alone is not enough. What you assert on is what matters.\n",
      "section": "api",
      "anchors": [
        "assert-on-a-derived-value-not-on-the-secret"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 159
    },
    {
      "id": "api/commands/env#avoid-its-and-invoke-on-the-yielded-object",
      "doc_id": "api/commands/env",
      "heading": "Avoid .its() and .invoke() on the yielded object",
      "heading_level": 3,
      "content_markdown": "### Avoid .its() and .invoke() on the yielded object\n\n[`.its()`](/llm/markdown/api/commands/its.md) and [`.invoke()`](/llm/markdown/api/commands/invoke.md) both add the subject they were applied to and the value they yield to the console output, so `cy.env(['apiKey']).its('apiKey')` prints the environment variable value twice. Read the property inside a `.then()` callback instead.\n\n**Incorrect Usage**\n\n```\n// ❌ Prints the environment variable value to the console output twice\ncy.env(['apiKey']).its('apiKey')\n```\n\n**Correct Usage**\n\n```\ncy.env(['apiKey']).then(({ apiKey }) => {\n  // ✅ Use apiKey here\n})\n```\n",
      "section": "api",
      "anchors": [
        "avoid-its-and-invoke-on-the-yielded-object"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 103
    },
    {
      "id": "api/commands/env#keep-the-value-out-of-downstream-command-logs",
      "doc_id": "api/commands/env",
      "heading": "Keep the value out of downstream command logs",
      "heading_level": 3,
      "content_markdown": "### Keep the value out of downstream command logs\n\nCommands that accept a `log` option, such as [`cy.request()`](/llm/markdown/api/commands/request.md) and [`.type()`](/llm/markdown/api/commands/type.md), leave their entry out of the Command Log when you pass `{ log: false }`. Use it on any command you hand the value to:\n\n```\ncy.env(['apiKey']).then(({ apiKey }) => {\n  cy.request({\n    url: 'https://api.example.com/users',\n    headers: { Authorization: `Bearer ${apiKey}` },\n    log: false,\n  })\n\n  cy.get('[data-testid=\"token-field\"]').type(apiKey, { log: false })\n})\n```\n\n`{ log: false }` hides the entry from the Command Log. It does not redact the value, and it has no effect on assertions.\n",
      "section": "api",
      "anchors": [
        "keep-the-value-out-of-downstream-command-logs"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 125
    },
    {
      "id": "api/commands/env#why-use-cy-env",
      "doc_id": "api/commands/env",
      "heading": "Why use cy.env()?",
      "heading_level": 2,
      "content_markdown": "## Why use cy.env()?\n\n`cy.env()` was introduced to replace `Cypress.env()`, which was deprecated in Cypress 15.10.0 and removed in Cypress 16.0.\n\n### Secure access to sensitive values\n\nUnlike `Cypress.env()` (removed in Cypress 16.0), which hydrated **all** environment variables into the browser:\n\n*   `cy.env()` only exposes the variables you explicitly request\n*   Variables are not automatically serialized into browser state\n*   Only requested variables are passed into `cy.origin()` contexts\n*   Sensitive data is easier to audit and control\n\nThis reduces accidental exposure and limits the blast radius of secrets.\n\n### When to use cy.env() vs Cypress.expose()\n\nBoth [`cy.env()`](/llm/markdown/api/commands/env.md) and [`Cypress.expose()`](/llm/markdown/api/cypress-api/expose.md) provide access to configuration values in Cypress, but they serve different security and execution needs. Choosing the right API helps avoid accidental exposure of sensitive data and keeps configuration intent clear.\n\n#### Use Cypress.expose() for public configuration\n\nRecommended when:\n\n*   **Values are public or non-sensitive** - Examples include feature flags, API versions, environment labels, or plugin configuration that is safe to appear in browser state.\n*   **Synchronous access is needed** - `Cypress.expose()` returns values immediately, without requiring Cypress command chaining.\n\n#### Use `cy.env()` for sensitive or secret values\n\nChoose `cy.env()` when security, scoping, and controlled access matter. Recommended when:\n\n*   **Values are sensitive** - API keys, passwords, tokens, or any data that should not be broadly exposed to the browser.\n*   **Security is a priority** - `cy.env()` only exposes the variables you explicitly request and does not automatically serialize them into browser state.\n*   **You're already working within Cypress command chains**: `cy.env()` is asynchronous and designed to be used inside Cypress tests and hooks.\n\n**Example: choosing the right API**\n\n```\n// ✅ Use cy.env() for sensitive values\ncy.env(['apiKey']).then(({ apiKey }) => {\n  cy.request({\n    url: 'https://api.example.com/users',\n    headers: { Authorization: `Bearer ${apiKey}` },\n  })\n})\n\n// ✅ Use Cypress.expose() for public configuration\nconst apiVersion = Cypress.expose('apiVersion') // Synchronous, public value\nconst featureFlag = Cypress.expose('featureFlag') // Safe to expose in browser\n```\n\nSee [`Cypress.expose()`](/llm/markdown/api/cypress-api/expose.md) for more details.\n",
      "section": "api",
      "anchors": [
        "why-use-cy-env"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 431
    },
    {
      "id": "api/commands/env#secure-access-to-sensitive-values",
      "doc_id": "api/commands/env",
      "heading": "Secure access to sensitive values",
      "heading_level": 3,
      "content_markdown": "### Secure access to sensitive values\n\nUnlike `Cypress.env()` (removed in Cypress 16.0), which hydrated **all** environment variables into the browser:\n\n*   `cy.env()` only exposes the variables you explicitly request\n*   Variables are not automatically serialized into browser state\n*   Only requested variables are passed into `cy.origin()` contexts\n*   Sensitive data is easier to audit and control\n\nThis reduces accidental exposure and limits the blast radius of secrets.\n",
      "section": "api",
      "anchors": [
        "secure-access-to-sensitive-values"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 89
    },
    {
      "id": "api/commands/env#when-to-use-cy-env-vs-cypress-expose",
      "doc_id": "api/commands/env",
      "heading": "When to use cy.env() vs Cypress.expose()",
      "heading_level": 3,
      "content_markdown": "### When to use cy.env() vs Cypress.expose()\n\nBoth [`cy.env()`](/llm/markdown/api/commands/env.md) and [`Cypress.expose()`](/llm/markdown/api/cypress-api/expose.md) provide access to configuration values in Cypress, but they serve different security and execution needs. Choosing the right API helps avoid accidental exposure of sensitive data and keeps configuration intent clear.\n\n#### Use Cypress.expose() for public configuration\n\nRecommended when:\n\n*   **Values are public or non-sensitive** - Examples include feature flags, API versions, environment labels, or plugin configuration that is safe to appear in browser state.\n*   **Synchronous access is needed** - `Cypress.expose()` returns values immediately, without requiring Cypress command chaining.\n\n#### Use `cy.env()` for sensitive or secret values\n\nChoose `cy.env()` when security, scoping, and controlled access matter. Recommended when:\n\n*   **Values are sensitive** - API keys, passwords, tokens, or any data that should not be broadly exposed to the browser.\n*   **Security is a priority** - `cy.env()` only exposes the variables you explicitly request and does not automatically serialize them into browser state.\n*   **You're already working within Cypress command chains**: `cy.env()` is asynchronous and designed to be used inside Cypress tests and hooks.\n\n**Example: choosing the right API**\n\n```\n// ✅ Use cy.env() for sensitive values\ncy.env(['apiKey']).then(({ apiKey }) => {\n  cy.request({\n    url: 'https://api.example.com/users',\n    headers: { Authorization: `Bearer ${apiKey}` },\n  })\n})\n\n// ✅ Use Cypress.expose() for public configuration\nconst apiVersion = Cypress.expose('apiVersion') // Synchronous, public value\nconst featureFlag = Cypress.expose('featureFlag') // Safe to expose in browser\n```\n\nSee [`Cypress.expose()`](/llm/markdown/api/cypress-api/expose.md) for more details.\n",
      "section": "api",
      "anchors": [
        "when-to-use-cy-env-vs-cypress-expose"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 313
    },
    {
      "id": "api/commands/env#use-cypress-expose-for-public-configuration",
      "doc_id": "api/commands/env",
      "heading": "Use Cypress.expose() for public configuration",
      "heading_level": 4,
      "content_markdown": "#### Use Cypress.expose() for public configuration\n\nRecommended when:\n\n*   **Values are public or non-sensitive** - Examples include feature flags, API versions, environment labels, or plugin configuration that is safe to appear in browser state.\n*   **Synchronous access is needed** - `Cypress.expose()` returns values immediately, without requiring Cypress command chaining.\n",
      "section": "api",
      "anchors": [
        "use-cypress-expose-for-public-configuration"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 65
    },
    {
      "id": "api/commands/env#use-cy-env-for-sensitive-or-secret-values",
      "doc_id": "api/commands/env",
      "heading": "Use cy.env() for sensitive or secret values",
      "heading_level": 4,
      "content_markdown": "#### Use `cy.env()` for sensitive or secret values\n\nChoose `cy.env()` when security, scoping, and controlled access matter. Recommended when:\n\n*   **Values are sensitive** - API keys, passwords, tokens, or any data that should not be broadly exposed to the browser.\n*   **Security is a priority** - `cy.env()` only exposes the variables you explicitly request and does not automatically serialize them into browser state.\n*   **You're already working within Cypress command chains**: `cy.env()` is asynchronous and designed to be used inside Cypress tests and hooks.\n\n**Example: choosing the right API**\n\n```\n// ✅ Use cy.env() for sensitive values\ncy.env(['apiKey']).then(({ apiKey }) => {\n  cy.request({\n    url: 'https://api.example.com/users',\n    headers: { Authorization: `Bearer ${apiKey}` },\n  })\n})\n\n// ✅ Use Cypress.expose() for public configuration\nconst apiVersion = Cypress.expose('apiVersion') // Synchronous, public value\nconst featureFlag = Cypress.expose('featureFlag') // Safe to expose in browser\n```\n\nSee [`Cypress.expose()`](/llm/markdown/api/cypress-api/expose.md) for more details.\n",
      "section": "api",
      "anchors": [
        "use-cy-env-for-sensitive-or-secret-values"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 192
    },
    {
      "id": "api/commands/env#migrate-from-cypress-env",
      "doc_id": "api/commands/env",
      "heading": "Migrate from Cypress.env()",
      "heading_level": 2,
      "content_markdown": "## Migrate from Cypress.env()\n\n`cy.env()` replaces the removed `Cypress.env()` API, which was deprecated in Cypress 15.10.0 and removed in Cypress 16.0.\n\nOn Cypress ^15.10.0, after migrating all usages, you can prevent future use of `Cypress.env()` by setting `allowCypressEnv: false` in your Cypress configuration. In Cypress 16.0, `allowCypressEnv` has been removed — `Cypress.env()` is no longer available regardless of configuration.\n\n**Cypress ^15.10.0 only:**\n\n*   cypress.config.js\n*   cypress.config.ts\n\n```\nconst { defineConfig } = require('cypress')\n\nmodule.exports = defineConfig({\n  allowCypressEnv: false,\n})\n```\n\n```\nimport { defineConfig } from 'cypress'\n\nexport default defineConfig({\n  allowCypressEnv: false,\n})\n```\n\nSee the [Migration Guide](/llm/markdown/app/references/migration-guide.md#Migrating-away-from-Cypressenv) for detailed migration instructions.\n",
      "section": "api",
      "anchors": [
        "migrate-from-cypress-env"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 136
    },
    {
      "id": "api/commands/env#notes",
      "doc_id": "api/commands/env",
      "heading": "Notes",
      "heading_level": 2,
      "content_markdown": "## Notes\n\n### Read-only behavior\n\n`cy.env()` is **read-only** and cannot set environment variables at runtime.\n\nSee the [Environment Variables & Secrets](/llm/markdown/app/guides/environment-variables.md) guide for more details on setting environment variables.\n\n### Test configuration overrides\n\nEnvironment variables cannot be set using [test configuration](/llm/markdown/app/references/configuration.md#Test-Configuration). On Cypress ^15.10.0, this was enforced when `allowCypressEnv` was set to `false`. In Cypress 16.0, `env` in test configuration overrides has been removed entirely — if absolutely necessary, `expose` can be used instead.\n\n### Case sensitivity\n\nVariable names are case-sensitive and must match exactly how they are defined in your configuration:\n\n```\n// Configuration\n{\n  env: {\n    apiUrl: 'https://api.example.com',\n  }\n}\n\n// In test\ncy.env(['apiUrl'])  // ✅ Gets 'https://api.example.com'\ncy.env(['APIURL']) // ❌ Returns undefined\n```\n",
      "section": "api",
      "anchors": [
        "notes"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 155
    },
    {
      "id": "api/commands/env#test-configuration-overrides",
      "doc_id": "api/commands/env",
      "heading": "Test configuration overrides",
      "heading_level": 3,
      "content_markdown": "### Test configuration overrides\n\nEnvironment variables cannot be set using [test configuration](/llm/markdown/app/references/configuration.md#Test-Configuration). On Cypress ^15.10.0, this was enforced when `allowCypressEnv` was set to `false`. In Cypress 16.0, `env` in test configuration overrides has been removed entirely — if absolutely necessary, `expose` can be used instead.\n",
      "section": "api",
      "anchors": [
        "test-configuration-overrides"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 60
    },
    {
      "id": "api/commands/env#case-sensitivity",
      "doc_id": "api/commands/env",
      "heading": "Case sensitivity",
      "heading_level": 3,
      "content_markdown": "### Case sensitivity\n\nVariable names are case-sensitive and must match exactly how they are defined in your configuration:\n\n```\n// Configuration\n{\n  env: {\n    apiUrl: 'https://api.example.com',\n  }\n}\n\n// In test\ncy.env(['apiUrl'])  // ✅ Gets 'https://api.example.com'\ncy.env(['APIURL']) // ❌ Returns undefined\n```\n",
      "section": "api",
      "anchors": [
        "case-sensitivity"
      ],
      "path": "/llm/json/chunked/api/commands/env.json",
      "token_estimate": 56
    }
  ]
}