---
id: api/commands/fixture
title: cy.fixture()
description: Load a fixed set of data located in a file in Cypress.
section: api
source_path: docs/api/commands/fixture.mdx
version: f60251bf707b0077a9535579c9f90d615440cc35
updated_at: '2026-10-16T10:56:58.670Z'
---
# fixture

Load a fixed set of data located in a file.

Tests are easiest to trust when every run starts from the same data. `cy.fixture()` loads known test data, such as JSON records, images, and CSV files, from your [`fixturesFolder`](/llm/markdown/app/references/configuration.md#Folders--Files). That keeps the data out of your spec code, lets many tests share it, and means a test fails because your app changed, not because the data did.

Reach for `cy.fixture()` when you need to:

*   Stub network responses with [`cy.intercept()`](/llm/markdown/api/commands/intercept.md), so your tests don't depend on a live backend or on data that changes between runs
*   Fill in forms or check the page against the same known records every time
*   Upload a sample file through a file input with [`.selectFile()`](/llm/markdown/api/commands/selectfile.md)

To read a file that changes while your tests run, or a file your app produces, use [`cy.readFile()`](/llm/markdown/api/commands/readfile.md) instead. See [How `cy.fixture()` differs from `cy.readFile()`](#How-cyfixture-differs-from-cyreadFile).

## Syntax

```
cy.fixture(filePath)
cy.fixture(filePath, encoding)
cy.fixture(filePath, options)
cy.fixture(filePath, encoding, options)
```

### Usage

**Correct Usage**

```
cy.fixture('users').as('usersJson') // load data from users.json
cy.fixture('logo.png').then((logo) => {
  // load data from logo.png
})
```

### Arguments

**filePath _(String)_**

A path to a file within the [`fixturesFolder`](/llm/markdown/app/references/configuration.md#Folders--Files) , which defaults to `cypress/fixtures`.

You can nest fixtures within folders and reference them by defining the path from the fixturesFolder:

```
cy.fixture('users/admin.json') // Get data from {fixturesFolder}/users/admin.json
```

**encoding _(String)_**

The encoding to be used when reading the file. The following encodings are supported:

*   `'ascii'`
*   `'base64'`
*   `'binary'`
*   `'hex'`
*   `'latin1'`
*   `'utf8'`
*   `'utf-8'`
*   `'ucs2'`
*   `'ucs-2'`
*   `'utf16le'`
*   `'utf-16le'`
*   `null`

Passing an encoding yields the raw file contents without parsing them, whatever the file extension. For example, `cy.fixture('users.json', 'utf8')` yields the JSON as a string rather than an object. Passing `null` yields the contents as a [`Cypress.Buffer`](/llm/markdown/api/utilities/buffer.md) instance.

**options _(Object)_**

Pass in an options object to change the default behavior of `cy.fixture()`.

| Option | Default | Description |
| --- | --- | --- |
| `timeout` | [`responseTimeout`](/llm/markdown/app/references/configuration.md#Timeouts) | Time to wait for `cy.fixture()` to resolve before [timing out](#Timeouts) |

### Yields

*   `cy.fixture()` yields the contents of the file. Formatting is determined by its file extension, unless you pass an `encoding`.
*   `cy.fixture()` yields a copy of the cached contents, so changing the yielded object does not affect later `cy.fixture()` calls for the same file.
*   The yielded subject is **not** updated if the contents change on disk. See [How Cypress caches fixture data](#How-Cypress-caches-fixture-data) for when Cypress reads the file again.

## Examples

### JSON

#### Load a `users.json` fixture

```
cy.fixture('users.json').as('usersData')
```

#### Omit the fixture file's extension

When no extension is passed to `cy.fixture()`, Cypress first looks for a file with exactly that name. If there isn't one, Cypress searches for files with the specified name and a supported extension within the [`fixturesFolder`](/llm/markdown/app/references/configuration.md#Folders--Files) (which defaults to `cypress/fixtures`) and resolves the first one.

```
cy.fixture('admin').as('adminJSON')
```

The example above would resolve in the following order:

1.  `cypress/fixtures/admin.json`
2.  `cypress/fixtures/admin.js`
3.  `cypress/fixtures/admin.html`
4.  `cypress/fixtures/admin.txt`
5.  `cypress/fixtures/admin.csv`
6.  `cypress/fixtures/admin.png`
7.  `cypress/fixtures/admin.jpg`
8.  `cypress/fixtures/admin.jpeg`
9.  `cypress/fixtures/admin.gif`
10.  `cypress/fixtures/admin.tif`
11.  `cypress/fixtures/admin.tiff`
12.  `cypress/fixtures/admin.zip`

#### Import a JSON fixture into your spec

If you are loading a JSON fixture, you can use the `import` statement and let the bundler load it:

cypress/e2e/spec.cy.js

```
import user from '../fixtures/user.json'
it('loads the same object', () => {
  cy.fixture('user').then((userFixture) => {
    expect(user, 'the same data').to.deep.equal(userFixture)
  })
})
```

#### Generate a test for each record in a fixture

To create one test per fixture record, `import` the fixture. `cy.fixture()` supplies data inside a test, but a loop inside its callback can't add new `it()` blocks.

cypress/e2e/users.cy.js

```
import users from '../fixtures/users.json'

describe('User profiles', () => {
  users.forEach((user) => {
    it(`shows the profile for ${user.name}`, () => {
      cy.visit(`/users/${user.id}`)
      cy.contains('h1', user.name)
    })
  })
})
```

#### Type fixture data in TypeScript

`cy.fixture()` accepts a type argument that describes the yielded contents. Cypress doesn't check the file against the type, so keep the two in sync.

```
type User = {
  id: number
  name: string
  email: string
}

cy.fixture<User[]>('users').then((users) => {
  // users is typed as User[]
  cy.get('[data-cy="user-email"]').first().should('have.text', users[0].email)
})
```

#### Read a JSON fixture as raw text

Pass an encoding to yield the file's contents as a string instead of the parsed object. This helps when you want the exact text of the file, such as to compare it with a raw request body.

```
cy.fixture('users.json', 'utf8').then((raw) => {
  expect(raw).to.be.a('string')
  expect(raw).to.include('"email"')
})
```

### Images

#### Image fixtures yield `base64` strings by default

```
cy.fixture('images/logo.png').then((logo) => {
  // logo will be encoded as base64
  // and should look something like this:
  // aIJKnwxydrB10NVWqhlmmC+ZiWs7otHotSAAAOw==...
})
```

#### Read an image fixture as a `Cypress.Buffer`

```
cy.fixture('images/logo.png', null).then((logo) => {
  // logo will be read as a buffer
  // and should look something like this:
  // Buffer([0, 0, ...])
  expect(Cypress.Buffer.isBuffer(logo)).to.be.true
})
```

### File uploads

#### Upload a fixture with `.selectFile()`

Load the fixture with a `null` encoding so it yields a `Cypress.Buffer`, alias it, and pass the alias to [`.selectFile()`](/llm/markdown/api/commands/selectfile.md). Cypress keeps the fixture's file name, so the upload arrives as `avatar.png`.

```
cy.fixture('images/avatar.png', null).as('avatar')
cy.get('input[type="file"]').selectFile('@avatar')
```

### Audio

#### Play an MP3 fixture in the browser

```
cy.fixture('audio/sound.mp3', 'base64').then((mp3) => {
  const uri = 'data:audio/mp3;base64,' + mp3
  const audio = new Audio(uri)

  audio.play()
})
```

### Accessing fixture data

#### Stub a network response with fixture data

```
cy.fixture('users').then((json) => {
  cy.intercept('GET', '/users/**', json)
})
```

#### Load a fixture in `beforeEach()` and read it with `cy.get()`

Aliases are cleared between tests, so load the fixture in a `beforeEach()` hook and read the alias back with [`cy.get()`](/llm/markdown/api/commands/get.md#Alias). This works with arrow functions, unlike the [`this` context](#Sharing-fixture-data-through-the-this-context).

```
describe('User list', () => {
  beforeEach(() => {
    cy.fixture('users').as('users')
  })

  it('shows a row for every user', () => {
    cy.visit('/users')
    cy.get('@users').then((users) => {
      cy.get('[data-cy="user-row"]').should('have.length', users.length)
    })
  })
})
```

#### Bootstrap your app's data with fixtures

[Check out our example recipe using `cy.fixture()` to bootstrap data for our application.](/llm/markdown/app/references/recipes.md#Server-Communication)

#### Change fixture data before stubbing a response

You can modify fixture data directly before visiting a URL or mounting a component that makes a network request to that URL.

*   End-to-End Test
*   Component Test

```
cy.fixture('user').then((user) => {
  user.firstName = 'Jane'
  cy.intercept('GET', '/users/1', user).as('getUser')
})

cy.visit('/users')
cy.wait('@getUser').then(({ response }) => {
  expect(response.body.firstName).to.eq('Jane')
})
```

```
cy.fixture('user').then((user) => {
  user.firstName = 'Jane'
  cy.intercept('GET', '/users/1', user).as('getUser')
})

cy.mount(<Users />)
cy.wait('@getUser').then(({ response }) => {
  expect(response.body.firstName).to.eq('Jane')
})
```

## Notes

### How `cy.fixture()` differs from `cy.readFile()`

Both commands read a file from disk, but they answer different questions. `cy.fixture()` answers "what data should this test start with?" while [`cy.readFile()`](/llm/markdown/api/commands/readfile.md) answers "what's in this file right now?" Use `cy.fixture()` for known data that stays the same during the run, and `cy.readFile()` for files that change or that your app creates. For when to reach for a static `import` or [`cy.task()`](/llm/markdown/api/commands/task.md) instead, see [Choosing how to load test data in Cypress](/llm/markdown/app/core-concepts/writing-and-organizing-tests.md#Choosing-how-to-load-test-data-in-Cypress).

|  | `cy.fixture()` | `cy.readFile()` |
| --- | --- | --- |
| Path is relative to | `fixturesFolder` | The project root |
| File extension | Optional | Required |
| Reads from disk | Once per path and encoding, then yields the cached copy | On every call |
| Retries until assertions pass | No | Yes, reading the file again on each retry |
| Images by default | A `base64` string | A `utf8` string |
| Default timeout | `responseTimeout` | `defaultCommandTimeout` |
| Command Log | Not logged | Logged |
| Missing file | Always fails | Can be asserted with `.should('not.exist')` |

### Serve a fixture directly from `cy.intercept()`

Fixtures can also be referenced directly without using the `cy.fixture()` command by using the special property `fixture` on the [`cy.intercept()`](/llm/markdown/api/commands/intercept.md) `StaticResponse` object.

```
cy.intercept('GET', '/users/**', { fixture: 'users' })
```

The Command Log's **Routes** panel lists the route as stubbed, and each request it answers appears in the test body without a live server behind it:

`cy.intercept()` serves image and `.zip` fixtures as raw bytes. Other binary files, such as `.mp4` or `.pdf`, are read as `utf8` text by default, which corrupts them. To serve one of those byte for byte, add `null` as the encoding after a comma:

```
cy.intercept('GET', '/media/intro.mp4', { fixture: 'media/intro.mp4,null' })
```

You can pass any other supported encoding the same way.

### How Cypress validates JSON and JavaScript fixtures

Cypress automatically validates your fixtures. If your `.json` or `.js` files contain syntax errors, the test fails with an error that names the fixture and describes the problem.

A `.js` fixture is evaluated as a single JavaScript expression, such as an object literal (`{ name: 'Jane' }`), rather than loaded as a module.

### How Cypress chooses a fixture's encoding

When you don't pass an encoding, Cypress reads the file based on its extension:

| Extension | Yields |
| --- | --- |
| `.json` | The parsed JSON |
| `.js` | The evaluated JavaScript expression |
| `.png`, `.jpg`, `.jpeg`, `.gif`, `.tif`, `.tiff`, `.zip` | A `base64` string |
| `.html`, `.txt`, `.csv`, and every other extension | A `utf8` string |

To read a file differently, pass an encoding as the second argument of `cy.fixture()`. You can specify `null` as the encoding to read the file as a [`Cypress.Buffer`](/llm/markdown/api/utilities/buffer.md) instance instead.

These defaults describe what `cy.fixture()` yields. When you serve a fixture from [`cy.intercept()`](#Serve-a-fixture-directly-from-cyintercept), image and `.zip` fixtures are sent as raw bytes instead of `base64`.

### Sharing fixture data through the `this` context

If you store and access the fixture data using `this` test context object, make sure to use `function () { ... }` callbacks. Otherwise the test engine will NOT have `this` pointing at the test context.

```
describe('User page', () => {
  beforeEach(function () {
    // "this" points at the test context object
    cy.fixture('user').then((user) => {
      // "this" is still the test context object
      this.user = user
    })
  })

  // the test callback is in "function () { ... }" form
  it('has user', function () {
    // this.user exists
    expect(this.user.firstName).to.equal('Jane')
  })
})
```

### Loading large files with `cy.fixture()`

#### Why large fixtures can crash or stall Cypress

`cy.fixture()` reads the **entire file into memory** and transfers its contents from the Cypress Node.js server process to the browser test runner over an internal WebSocket connection. There is no explicit file size limit in Cypress itself, but large files — especially binary files like `.zip` archives — can cause Cypress to crash or become unresponsive due to:

*   **Memory pressure**: The complete file must fit in available RAM. Cypress keeps the contents in the fixture cache and yields a separate copy, so each loaded fixture takes up memory more than once. By default, binary files such as images and `.zip` archives are also converted to a `base64` string in the browser, which is about a third larger than the file itself.
*   **Single-message transfer**: File contents are sent as a single message over the internal socket, so the whole payload is buffered at once.

As a practical guideline, avoid using `cy.fixture()` with files larger than a few megabytes. Smaller test fixtures (representative subsets of production data) are preferable wherever possible.

#### Upload a large file with `.selectFile()` and a path

If your goal is to simulate a file upload through an `<input type="file">` element, use [`.selectFile()`](/llm/markdown/api/commands/selectfile.md) with a path string rather than loading the fixture first and then setting the input manually:

```
// ✅ Preferred for file upload simulation
cy.get('input[type="file"]').selectFile('cypress/fixtures/large.zip')
```

#### Check a large file in Node.js with `cy.task()`

For scenarios where you must work with large files but do not need to transfer their full contents to the browser (for example, verifying file metadata or invoking a server-side operation), use [`cy.task()`](/llm/markdown/api/commands/task.md) to keep the operation in the Node.js context:

*   cypress.config.js
*   cypress.config.ts

```
const { defineConfig } = require('cypress')
const { statSync } = require('fs')

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      on('task', {
        getFileSize(filePath) {
          const { size } = statSync(filePath)
          return size
        },
      })
    },
  },
})
```

```
import { defineConfig } from 'cypress'
import { statSync } from 'fs'

export default defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      on('task', {
        getFileSize(filePath: string) {
          const { size } = statSync(filePath)
          return size
        },
      })
    },
  },
})
```

```
// in your test
cy.task('getFileSize', 'cypress/fixtures/large.zip').then((size) => {
  expect(size).to.be.greaterThan(0)
})
```

### How Cypress caches fixture data

The first time you load a fixture, Cypress caches its contents, keyed on the path exactly as you wrote it and the encoding. Later `cy.fixture()` calls with the same path and encoding yield the cached contents, even if the file has changed on disk. Because the key is the path as written, `cy.fixture('users')` and `cy.fixture('users.json')` are cached separately, so use one form consistently to read the file only once.

When you write to a file inside the [`fixturesFolder`](/llm/markdown/app/references/configuration.md#Folders--Files) with [`cy.writeFile()`](/llm/markdown/api/commands/writefile.md), Cypress clears that file from the cache, so the next `cy.fixture()` call reads the new contents:

```
cy.writeFile('cypress/fixtures/todo.json', { title: 'New data' })
cy.fixture('todo').its('title').should('eq', 'New data')
```

Cypress doesn't detect changes made any other way, such as from [`cy.task()`](/llm/markdown/api/commands/task.md) or another process. To read a file that changes during your tests, use [`cy.readFile()`](/llm/markdown/api/commands/readfile.md) instead.

#### Fixtures in `cy.intercept()` are read when the route is added

The `fixture` property of a [`cy.intercept()`](/llm/markdown/api/commands/intercept.md) `StaticResponse` reads the file when Cypress registers the route. Overwriting the file afterwards doesn't change what that route replies with, so the following **will not work**:

```
// 🚨 DOES NOT WORK
cy.intercept('GET', '/todos/1', { fixture: 'todo' }).as('todo')
// application requests the /todos/1 resource
// the intercept replies with the object from todo.json file

cy.wait('@todo').then(() => {
  cy.writeFile('cypress/fixtures/todo.json', { title: 'New data' })
})
// application requests the /todos/1 resource again
// the intercept replies with the object read from todo.json
// when the route was added and NOT { "title": "New data" }
```

In this situation, respond to the network request with the object and add a new intercept when the data changes:

```
// ✅ RESPOND WITH OBJECT
cy.fixture('todo.json').then((todo) => {
  cy.intercept('GET', '/todos/1', { body: todo }).as('todo')
  // application requests the /todos/1 resource
  // the intercept replies with the initial object

  cy.wait('@todo').then(() => {
    // modify the response object
    todo.title = 'New data'
    // and override the intercept
    cy.intercept('GET', '/todos/1', { body: todo })
  })
})
```

## Rules

### Requirements

*   `cy.fixture()` requires being chained off of `cy`.
*   `cy.fixture()` requires [`fixturesFolder`](/llm/markdown/app/references/configuration.md#Folders--Files) to be set. It fails if `fixturesFolder` is `false`.

### Assertions

*   `cy.fixture()` will only run assertions you have chained once, and will not [retry](/llm/markdown/app/core-concepts/retry-ability.md).

### Timeouts

*   `cy.fixture()` can time out waiting for the Cypress server to send the fixture. It waits for the `timeout` option, which defaults to [`responseTimeout`](/llm/markdown/app/references/configuration.md#Timeouts).
*   `cy.fixture()` yields cached contents without waiting on the server, so a cached fixture never times out.

## Command Log

*   `cy.fixture()` does _not_ log in the Command Log

## History

| Version | Changes |
| --- | --- |
| [15.18.0](/llm/markdown/app/references/changelog.md#15-18-0) | An aliased fixture keeps its file name for `.selectFile()` when a later test loads the same fixture. |
| [15.0.0](/llm/markdown/app/references/changelog.md#15-0-0) | `cy.writeFile()` clears the cache for a fixture it writes. An explicit `encoding` always yields raw file contents. |

## See also

*   [Guide: Variables and Aliases](/llm/markdown/app/core-concepts/variables-and-aliases.md)
*   [`cy.intercept()`](/llm/markdown/api/commands/intercept.md)
*   [`cy.readFile()`](/llm/markdown/api/commands/readfile.md) for a similar command without caching and with built-in retryability
*   [`.selectFile()`](/llm/markdown/api/commands/selectfile.md) for simulating file uploads, including with large files
*   [`cy.task()`](/llm/markdown/api/commands/task.md) for keeping large file operations in the Node.js context
