> For the complete documentation index, see [llms.txt](https://nicolasiensen.gitbook.io/vcr/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://nicolasiensen.gitbook.io/vcr/v-5.1.0/cassettes/format.md).

# Cassette Format

VCR Cassettes are files that contain all of the information about the requests and corresponding responses in a human-readable/editable format. A cassette contains an array of HTTP interactions, each of which has the following:

* request
  * method
  * uri
  * body
    * encoding
    * string
  * headers
* response

  * status
    * code
    * message
  * headers
  * body
    * encoding
    * string
  * http version

  By default, VCR uses YAML to serialize this data. You can configure VCR to use a different serializer, either on a cassette-by-cassette basis, or as a default for all cassettes if you use the `default_cassette_options`.

  VCR supports the following serializers out of the box:
* `:yaml`--Uses ruby's standard library YAML. This may use psych or syck, depending on your ruby installation.
* `:syck`--Uses syck (the ruby 1.8 YAML engine). This is useful when using

  VCR on a project that must run in environments where psych is not available

  (such as on ruby 1.8), to ensure that syck is always used.
* `:psych`--Uses psych (the new ruby 1.9 YAML engine). This is useful when

  you want to ensure that psych is always used.
* `:json`--Uses [multi\_json](https://github.com/intridea/multi_json)

  to serialize the cassette data as JSON.
* `:compressed`--Wraps the default YAML serializer with Zlib, writing compressed cassettes to disk.

  You can also register a custom serializer using:

  VCR.configure do |config| config.cassette\_serializers\[:my\_custom\_serializer] = my\_serializer end

  Your serializer must implement the following methods:
* `file_extension`
* `serialize(hash)`
* `deserialize(string)`

## Request/Response data is saved to disk as YAML by default

*Given* a file named "cassette\_yaml.rb" with:

```
include_http_adapter_for("<http_lib>")

if ARGV.any?
  $server = start_sinatra_app do
    get('/:path') { ARGV[0] + ' ' + params[:path] }
  end
end

require 'vcr'

VCR.configure do |c|
  <configuration>
  c.cassette_library_dir = 'cassettes'
  c.before_record do |i|
    i.request.uri.sub!(/:\d+/, ':7777')
  end
end

VCR.use_cassette('example') do
  make_http_request(:get, "http://localhost:#{$server.port}/foo", nil, 'Accept-Encoding' => 'identity')
  make_http_request(:get, "http://localhost:#{$server.port}/bar", nil, 'Accept-Encoding' => 'identity')
end
```

*When* I successfully run `ruby cassette_yaml.rb 'Hello'`

*Then* the file "cassettes/example.yml" should contain YAML like:

```
---
http_interactions:
- request:
    method: get
    uri: http://localhost:7777/foo
    body:
      encoding: UTF-8
      string: ""
    headers:
      Accept-Encoding:
      - identity
  response:
    status:
      code: 200
      message: OK
    headers:
      Content-Type:
      - text/html;charset=utf-8
      Content-Length:
      - "9"
    body:
      encoding: UTF-8
      string: Hello foo
    http_version: "1.1"
  recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
- request:
    method: get
    uri: http://localhost:7777/bar
    body:
      encoding: UTF-8
      string: ""
    headers:
      Accept-Encoding:
      - identity
  response:
    status:
      code: 200
      message: OK
    headers:
      Content-Type:
      - text/html;charset=utf-8
      Content-Length:
      - "9"
    body:
      encoding: UTF-8
      string: Hello bar
    http_version: "1.1"
  recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
recorded_with: VCR 2.0.0
```

### Examples

| configuration          | http\_lib              |
| ---------------------- | ---------------------- |
| c.hook\_into :webmock  | net/http               |
| c.hook\_into :webmock  | httpclient             |
| c.hook\_into :webmock  | patron                 |
| c.hook\_into :webmock  | curb                   |
| c.hook\_into :webmock  | em-http-request        |
| c.hook\_into :webmock  | typhoeus               |
| c.hook\_into :typhoeus | typhoeus               |
| c.hook\_into :excon    | excon                  |
| c.hook\_into :faraday  | faraday (w/ net\_http) |

## Request/Response data can be saved as JSON

*Given* a file named "cassette\_json.rb" with:

```
include_http_adapter_for("net/http")

$server = start_sinatra_app do
  get('/:path') { ARGV[0] + ' ' + params[:path] }
end

require 'vcr'

VCR.configure do |c|
  c.hook_into :webmock
  c.cassette_library_dir = 'cassettes'
  c.before_record do |i|
    i.request.uri.sub!(/:\d+/, ':7777')
  end
  c.default_cassette_options = {
    :match_requests_on => [:method, :host, :path]
  }
end

VCR.use_cassette('example', :serialize_with => :json) do
  puts response_body_for(:get, "http://localhost:#{$server.port}/foo", nil, 'Accept-Encoding' => 'identity')
  puts response_body_for(:get, "http://localhost:#{$server.port}/bar", nil, 'Accept-Encoding' => 'identity')
end
```

*When* I run `ruby cassette_json.rb 'Hello'`

*Then* the file "cassettes/example.json" should contain JSON like:

```
{
  "http_interactions": [
    {
      "response": {
        "body": {
          "encoding": "UTF-8",
          "string": "Hello foo"
        },
        "http_version": null,
        "status": { "code": 200, "message": "OK" },
        "headers": {
          "Date": [ "Thu, 27 Oct 2011 06:16:31 GMT" ],
          "Content-Type": [ "text/html;charset=utf-8" ],
          "Content-Length": [ "9" ],
          "Server": [ "WEBrick/1.3.1 (Ruby/1.8.7/2011-06-30)" ],
          "Connection": [ "Keep-Alive" ]
        }
      },
      "request": {
        "uri": "http://localhost:7777/foo",
        "body": {
          "encoding": "UTF-8",
          "string": ""
        },
        "method": "get",
        "headers": {
          "Accept-Encoding": [ "identity" ]
        }
      },
      "recorded_at": "Tue, 01 Nov 2011 04:58:44 GMT"
    },
    {
      "response": {
        "body": {
          "encoding": "UTF-8",
          "string": "Hello bar"
        },
        "http_version": null,
        "status": { "code": 200, "message": "OK" },
        "headers": {
          "Date": [ "Thu, 27 Oct 2011 06:16:31 GMT" ],
          "Content-Type": [ "text/html;charset=utf-8" ],
          "Content-Length": [ "9" ],
          "Server": [ "WEBrick/1.3.1 (Ruby/1.8.7/2011-06-30)" ],
          "Connection": [ "Keep-Alive" ]
        }
      },
      "request": {
        "uri": "http://localhost:7777/bar",
        "body": {
          "encoding": "UTF-8",
          "string": ""
        },
        "method": "get",
        "headers": {
          "Accept-Encoding": [ "identity" ]
        }
      },
      "recorded_at": "Tue, 01 Nov 2011 04:58:44 GMT"
    }
  ],
  "recorded_with": "VCR 2.0.0"
}
```

*When* I run `ruby cassette_json.rb`

*Then* it should pass with:

```
Hello foo
Hello bar
```

## Request/Response data can be saved as compressed YAML

*Given* a file named "cassette\_compressed.rb" with:

```
include_http_adapter_for("net/http")

$server = start_sinatra_app do
  get('/:path') { ARGV[0] + ' ' + params[:path] }
end

require 'vcr'

VCR.configure do |c|
  c.hook_into :webmock
  c.cassette_library_dir = 'cassettes'
  c.before_record do |i|
    i.request.uri.sub!(/:\d+/, ':7777')
  end
  c.default_cassette_options = {
    :match_requests_on => [:method, :host, :path]
  }
end

VCR.use_cassette('example', :serialize_with => :compressed) do
  puts response_body_for(:get, "http://localhost:#{$server.port}/foo", nil, 'Accept-Encoding' => 'identity')
  puts response_body_for(:get, "http://localhost:#{$server.port}/bar", nil, 'Accept-Encoding' => 'identity')
end
```

*When* I run `ruby cassette_compressed.rb 'Hello'`

*Then* the file "cassettes/example.zz" should contain compressed YAML like:

```
---
http_interactions:
- request:
    method: get
    uri: http://localhost:7777/foo
    body:
      encoding: UTF-8
      string: ""
    headers:
      Accept-Encoding:
      - identity
  response:
    status:
      code: 200
      message: OK
    headers:
      Content-Type:
      - text/html;charset=utf-8
      Content-Length:
      - "9"
    body:
      encoding: UTF-8
      string: Hello foo
  recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
- request:
    method: get
    uri: http://localhost:7777/bar
    body:
      encoding: UTF-8
      string: ""
    headers:
      Accept-Encoding:
      - identity
  response:
    status:
      code: 200
      message: OK
    headers:
      Content-Type:
      - text/html;charset=utf-8
      Content-Length:
      - "9"
    body:
      encoding: UTF-8
      string: Hello bar
  recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
recorded_with: VCR 2.0.0
```

*When* I run `ruby cassette_compressed.rb`

*Then* it should pass with:

```
Hello foo
Hello bar
```

## Request/Response data can be saved using a custom serializer

*Given* a file named "cassette\_ruby.rb" with:

```
include_http_adapter_for("net/http")

$server = start_sinatra_app do
  get('/:path') { ARGV[0] + ' ' + params[:path] }
end

require 'vcr'

# purely for demonstration purposes; obviously, don't actually
# use ruby #inspect / #eval for your serialization...
ruby_serializer = Object.new
class << ruby_serializer
  def file_extension; "ruby"; end
  def serialize(hash); hash.inspect; end
  def deserialize(string); eval(string); end
end

VCR.configure do |c|
  c.hook_into :webmock
  c.cassette_library_dir = 'cassettes'
  c.cassette_serializers[:ruby] = ruby_serializer
  c.before_record do |i|
    i.request.uri.sub!(/:\d+/, ':7777')
  end
  c.default_cassette_options = {
    :match_requests_on => [:method, :host, :path]
  }
end

VCR.use_cassette('example', :serialize_with => :ruby) do
  puts response_body_for(:get, "http://localhost:#{$server.port}/foo", nil, 'Accept-Encoding' => 'identity')
  puts response_body_for(:get, "http://localhost:#{$server.port}/bar", nil, 'Accept-Encoding' => 'identity')
end
```

*When* I run `ruby cassette_ruby.rb 'Hello'`

*Then* the file "cassettes/example.ruby" should contain ruby like:

```
{"http_interactions"=>
  [{"request"=>
     {"method"=>"get",
      "uri"=>"http://localhost:7777/foo",
      "body"=>{"encoding"=>"UTF-8", "string"=>""},
      "headers"=>{"Accept"=>["*/*"], "Accept-Encoding"=>["identity"], "User-Agent"=>["Ruby"]}},
    "response"=>
     {"status"=>{"code"=>200, "message"=>"OK "},
      "headers"=>
       {"Content-Type"=>["text/html;charset=utf-8"],
        "Content-Length"=>["9"],
        "Connection"=>["Keep-Alive"]},
      "body"=>{"encoding"=>"UTF-8", "string"=>"Hello foo"},
      "http_version"=>nil},
    "recorded_at"=>"Tue, 01 Nov 2011 04:58:44 GMT"},
   {"request"=>
     {"method"=>"get",
      "uri"=>"http://localhost:7777/bar",
      "body"=>{"encoding"=>"UTF-8", "string"=>""},
      "headers"=>{"Accept"=>["*/*"], "Accept-Encoding"=>["identity"], "User-Agent"=>["Ruby"]}},
    "response"=>
     {"status"=>{"code"=>200, "message"=>"OK "},
      "headers"=>
       {"Content-Type"=>["text/html;charset=utf-8"],
        "Content-Length"=>["9"],
        "Connection"=>["Keep-Alive"]},
      "body"=>{"encoding"=>"UTF-8", "string"=>"Hello bar"},
      "http_version"=>nil},
    "recorded_at"=>"Tue, 01 Nov 2011 04:58:44 GMT"}],
 "recorded_with"=>"VCR 2.0.0"}
```

*When* I run `ruby cassette_ruby.rb`

*Then* it should pass with:

```
Hello foo
Hello bar
```
