Cassettes
One-liner: a cassette is a file of recorded request/response pairs, replayed in order when the same request comes in again.
On this page: What gets recorded · File format · Identical requests · Where cassettes live
What gets recorded
VCR::insertCassette('example') attaches a storage backend to a
Cassette. Every request that misses playback gets a real HTTP round trip, then the request and response are
recorded as one entry. On the next run, an incoming request that matches a recorded
one gets that recorded response back — no network call.
File format
Here's an actual YAML cassette entry, recorded from file_get_contents('http://example.com/hello'):
-
request:
method: GET
url: 'http://example.com/hello'
headers:
Host: example.com
response:
status:
code: 200
message: OK
headers:
Content-type: text/plain
body: 'Hello, php-vcr!'
curl_info:
url: 'http://example.com/hello'
http_code: 200
# ... (curl's full getinfo() array, useful for debugging but not required reading)
index: 0
What every field means
request— a serializedRequest: method, URL, headers, and (if present) body/post fields/post files.response— a serializedResponse: status, headers, body, plus curl's diagnosticcurl_infoarray (recorded for reference, not used during replay matching).index— see Identical requests below.
JSON storage records the exact same fields, just as JSON instead of YAML.
Identical requests
If a test makes the same request more than once, each occurrence gets recorded as its own cassette entry,
distinguished by an incrementing index — and replayed back in that same order:
-
request: { method: GET, url: '/counter', headers: { Host: example.com } }
response: { status: { code: 200, message: OK }, body: 'call-1' }
index: 0
-
request: { method: GET, url: '/counter', headers: { Host: example.com } }
response: { status: { code: 200, message: OK }, body: 'call-2' }
index: 1
This is controlled by
setRecordIdenticalRequests() (default true).
Set it to false if your test issues the same request a variable number of times across runs — every
occurrence then replays the first recorded response instead of advancing through the sequence.
📌 Note: cassettes recorded before php-vcr added the
indexfield still work — a missingindexfalls back to match-anything behaviour.
Where cassettes live
- Configured via
setCassettePath()(defaulttests/fixtures). - The file is named exactly the cassette name — no extension is appended.
- A cassette name with a path separator (
'api/users') auto-creates the subfolder. - Blackhole storage never writes a file at all.
← How VCR works · Next: Record Modes →