VCR (Ruby): record HTTP interactions and replay them in your test suite
Record your test suite's HTTP interactions and replay them during future test runs for fast, deterministic, accurate tests.
At a glance
- What is it?
- The vcr gem records real HTTP traffic into cassette files and replays it on later test runs. It suits Ruby projects that call external services in tests, and it is the wrong tool when you need live responses or non-HTTP dependencies.
- Who is it for?
- Adopt vcr if your Ruby test suite makes HTTP calls to third-party services and you want deterministic runs without network access. Do not adopt it for streaming, websocket or non-HTTP dependencies, and do not treat recorded cassettes as a substitute for integration tests against the real service.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 99 days ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What vcr solves for Ruby test suites
A test that calls a live HTTP endpoint fails for reasons that have nothing to do with your code: the remote service is down, the response changed, the CI runner has no outbound network, or the request is rate limited. vcr targets exactly that class of flakiness. Its README describes the goal as recording a test suite's HTTP interactions and replaying them during future runs for fast, deterministic, accurate tests.
The audience is Ruby developers writing unit or integration tests around code that talks to external HTTP services. That includes RSpec and Minitest suites, Cucumber features, and anything built on Net::HTTP. The README lists RSpec 1 and 2, Cucumber, Test::Unit, Capybara, Mechanize, Rest Client and HTTParty as libraries it is known to work with.
How cassettes, hooks and request matching fit together
The mechanism has three parts. A cassette is a recorded set of HTTP interactions stored on disk. A hook is the HTTP stubbing library vcr delegates to. A matcher decides whether an incoming request matches a recorded one.
You configure a cassette_library_dir, which is where cassette files are written, and hook_into, which selects the stubbing backend. The README names WebMock, Typhoeus, Faraday and Excon as supported hook targets. When a test runs inside a VCR.use_cassette block, vcr intercepts the HTTP call through the hook. On the first run there is no cassette, so the real request goes out and the request and response are written to a file named after the cassette. On later runs the request is matched against the recorded interactions and the stored response is returned without touching the network.
Matching is configurable. The README states that request matching can be based on HTTP method, URI, host, path, body and headers, and that you can implement a custom request matcher. Serialization is also pluggable: YAML and JSON are built in, and the README says a custom serializer can be implemented. Cassettes are plain files, so they can be read and edited. Responses can contain ERB, which the README lists as the mechanism for dynamic responses. There is also an option to re-record cassettes on a configurable interval.
Installing vcr and recording a first cassette
The README shows configuration inside spec_helper.rb, using test/unit and Net::HTTP. The cassette library directory must not collide with directories your framework already loads: the README warns that Rails and Minitest users should not use test/fixtures, because Rails will transitively load files in that directory as models.
require 'rubygems'
require 'test/unit'
require 'vcr'
VCR.configure do |config|
config.cassette_library_dir = "fixtures/vcr_cassettes"
config.hook_into :webmock
endWrap the HTTP call in a cassette block. The block name becomes the cassette name, so the example below writes fixtures/vcr_cassettes/synopsis.yml on the first run.
class VCRTest < Test::Unit::TestCase
def test_example_dot_com
VCR.use_cassette("synopsis") do
response = Net::HTTP.get_response(URI('http://www.iana.org/domains/reserved'))
assert_match /Example domains/, response.body
end
end
endRun the test once and the real request is made and recorded. Run it again and the README says vcr replays the response from iana.org. The same test then passes offline, and the replayed response carries the same headers and body as the recorded one. Before recording anything sensitive, read the Filter Sensitive Data page the README links to, and set up filtering first rather than after the cassette exists.
Where vcr stops being the right tool
The scope is HTTP. A cassette captures an HTTP interaction, so a dependency that is not HTTP (a database, a message queue, a gRPC service) is outside what vcr records, and the README does not claim otherwise.
The larger risk is staleness. A cassette is a snapshot. If the remote API changes a field name or a status code, your tests keep passing against the old recording, and the failure surfaces later, in production or in a manual check. The README's answer is the option to re-record cassettes on a configurable regular interval, plus the ability to edit cassettes by hand. Neither is automatic by default, and the README does not document a staleness warning or a rollback path for a bad re-record.
A second failure mode is the default posture of blocking unallowed requests. The README lists disabling all HTTP requests you do not explicitly allow as a feature. That is the correct default for catching accidental network calls, but it also means a newly added endpoint fails the suite until you either record a cassette or allow the request. Expect that friction on every new integration.
Finally, the project is candid about maintainer capacity. The README carries a Help Wanted note asking for more maintainers to review pull requests, issues and discussions. That is not a statement about code quality, but it is a real signal about how quickly issues and pull requests move.
vcr against WebMock alone, and against a contract-testing tool
WebMock is the closest alternative and is also a dependency of the common vcr setup. WebMock stubs HTTP at the library level: you write the expected request and the response you want returned, in Ruby, in the test. Nothing is recorded. The difference is where the response comes from. With WebMock you author it and you own its accuracy. With vcr you capture a real response once and replay it, so the recorded body and headers reflect what the service actually sent. The trade-off is that a hand-written WebMock stub is obvious in review, while a cassette is a large generated file that reviewers tend to scroll past.
If your concern is that a third-party API still honours the contract you depend on, a consumer-driven contract tool is a different approach again: the contract is negotiated with the provider and verified on their side, rather than recorded on yours. vcr cannot do that, because the recording says nothing about the provider's current behaviour.
Maintenance, upgrades and licence
The repository is not archived, and the last push was on 2026-06-23. The most recent release listed is v6.4.0 on 2025-12-22, following v6.3.1 on 2024-08-20 and v6.3.0 on 2024-08-19. That is a slow cadence, and combined with the Help Wanted note it is worth planning for: pin the gem version and read CHANGELOG.md before bumping.
The README states that vcr follows semantic versioning, with patch releases limited to bug fixes, minor releases adding backward-compatible features, and major releases containing backward-incompatible changes to the public API. The public API is defined by the rubydoc.info documentation, so the upgrade surface is the documented API rather than internal classes. The repository also carries an Upgrade.md file, which is the first place to look when a major version moves.
Ruby version support is bounded. VCR 6.x is tested on MRI 2.7 through 4.0. The README records that VCR 6.0.0 was the last version supporting Ruby 2.3 and above, and VCR 6.1.0 the last supporting 2.6 and above, with upcoming releases supporting 2.7 and above. If you are on an older interpreter, you are on an older vcr.
The licence field reports NOASSERTION, which means the repository's licence could not be matched to a standard identifier automatically. The repository does contain a LICENSE file, so read it directly rather than assuming MIT. This is not legal advice.
Editorial conclusion
Adopt vcr if your Ruby test suite makes HTTP calls to third-party services and you want deterministic runs without network access. Do not adopt it for streaming, websocket or non-HTTP dependencies, and do not treat recorded cassettes as a substitute for integration tests against the real service. Before committing, check that your Ruby version is covered by the 6.x compatibility list (MRI 2.7 through 4.0), that your HTTP library is one of the supported ones, and that filter_sensitive_data is configured before the first cassette is recorded, because a secret written into a cassette is a secret you now have to scrub by hand.
Frequently asked questions
What does VCR stand for in the vcr Ruby gem?
The README does not expand the acronym. It describes the gem only by what it does: recording a test suite's HTTP interactions and replaying them during future test runs.
How does vcr work in a Ruby test suite?
You configure a cassette_library_dir and hook_into a stubbing library such as WebMock, then wrap an HTTP call in VCR.use_cassette. The first run records the real request and response to a cassette file, and later runs replay the stored response instead of making the request.
Which HTTP libraries can vcr hook into?
The README lists WebMock, Typhoeus, Faraday and Excon as supported hook targets, and names Patron, Curb, HTTPClient, em-http-request, Net::HTTP and Typhoeus among the supported HTTP libraries. Anything built on Net::HTTP, such as Mechanize, HTTParty or Rest Client, is covered too.
Can I use test/fixtures as the cassette directory in Rails?
No. The README warns that Rails and Minitest users should not use test/fixtures, because Rails will transitively load any files in that directory as models. The README suggests alternatives such as fixtures/vcr_cassettes or test/vcr_cassettes.
Which Ruby versions does vcr 6.x support?
VCR 6.x is tested on MRI 2.7 through 4.0. The README notes that VCR 6.0.0 was the last version supporting Ruby 2.3 and above, and VCR 6.1.0 the last supporting 2.6 and above.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/vcr-vcr)