getsentry/responses
> A test utility that mocks the Python requests library by patching its transport adapter — no network, no live server.
GitHub repo · PyPI · License: Apache-2.0
Overview
responses intercepts calls made through the requests library and returns pre-registered fake responses instead of hitting the network. It was created by David Cramer in 20131 and is maintained under the Sentry (getsentry) organization. The API deliberately mirrors requests: you register a URL/method/body triple, run the code under test, and any matching outbound call is served from the registry rather than a socket.
The single most important fact about responses is the boundary of what it mocks: it patches requests.adapters.HTTPAdapter.send, so it only intercepts traffic that goes through the requests library2. Code that reaches for urllib3, http.client, httpx, or aiohttp directly passes straight through untouched — a ConnectionError or a real network call, not a mock. This tight coupling to requests is both why the library is small and predictable and why it is the wrong tool the moment your stack moves off requests.
It is aimed at unit and integration tests where you want deterministic HTTP behavior without standing up a fake server. As of 2026 it requires Python 3.8+ and requests >= 2.30.03, and remains one of the most widely used HTTP-mocking libraries in the Python test ecosystem.
Getting Started
pip install responses
import responses
import requests
@responses.activate
def test_fetch():
responses.get(
"http://example.com/api/user",
json={"id": 1, "name": "ada"},
status=200,
)
resp = requests.get("http://example.com/api/user")
assert resp.json()["name"] == "ada"
assert responses.calls[0].request.url == "http://example.com/api/user"
Any request that does not match a registered response raises requests.exceptions.ConnectionError, which makes accidental live traffic in tests fail loudly instead of leaking out.
Architecture / How It Works
responses does not run a server or bind a socket. When @responses.activate (or the RequestsMock context manager) is entered, it monkeypatches HTTPAdapter.send — the point where requests hands a PreparedRequest to its transport layer2. The patched send walks a registry of registered Response objects, runs each candidate through its matchers, and returns the first match as a synthetic requests.Response. On exit the original adapter method is restored.
Key moving parts:
- Registry — by default a
FirstMatchRegistry. It returns the first matching response; if several responses match the same request, the matched one is consumed and removed so the next call falls through to the following match.OrderedRegistryinstead ties responses strictly to insertion/invocation order, and you can subclassregistries.FirstMatchRegistryto implement custom lookup4. - Matchers — the
responses.matchersmodule supplies composable predicates (json_params_matcher,urlencoded_params_matcher,query_param_matcher,header_matcher,multipart_matcher,request_kwargs_matcher,fragment_identifier_matcher). Each is a callable returning(matched: bool, reason: str)and receives aPreparedRequestaugmented with extraparamsandreq_kwargsattributes. - Response body — can be a string, bytes, a JSON object (auto-sets
Content-Type), a callback (CallbackResponse), or anExceptioninstance, which is raised to simulate transport-level failures. - Passthrough —
add_passthru/passthru_prefixeslet selected URL prefixes reach the real network while everything else stays mocked.
Because interception happens at the adapter layer, the full requests machinery above it — sessions, auth, retries config, PreparedRequest construction, cookie jars — runs for real. That is why matchers see the actually-serialized body and headers, and it is also why anything below or beside the adapter (a custom transport, or a different HTTP library) is invisible to responses.
Production Notes
This is test-only tooling, but the operational footguns are real and recurring:
- Wrong library = silent no-op. If the code under test uses
httpx,aiohttp,urllib3, orurllibdirectly,responsesmocks nothing. This is the number-one surprise. Userespxforhttpxandvcrpy/HTTPrettyfor cross-library coverage. assert_all_requests_are_fireddefaults to True. WithRequestsMock(and the pytest fixture), any registered response that is never hit raises at teardown. Tests that over-register mocks fail in confusing ways; passassert_all_requests_are_fired=Falsewhen you intend some responses to be optional.- First-match consumption is order-sensitive. With the default registry, registering multiple responses for one URL means each call pops one. Tests that assume a fixed response for repeated calls to the same URL either need a single non-consumed response, a callback, or
OrderedRegistry— and reasoning about "reverse order" behavior trips people up. - Registering full URLs with query strings is deprecated. The old
match_querystringbehavior is deprecated; put query matching inmatchers.query_param_matcher/query_string_matcherand keep the bare path inurl5. - Module-level state moved.
responses.assert_all_requests_are_fired,responses.passthru_prefixes, andresponses.targetwere deprecated in 0.20.0 in favor ofresponses.mock.*; several matchers moved out of the top-level namespace intoresponses.matchersin 0.14.05. Old tutorials cite the removed paths. - Not designed for concurrency. The global
responses.mockobject and its patch of a shared adapter method make parallel use within a process fragile; keep it inside single-threaded test bodies. - Strict header matching needs a PreparedRequest. Because
requestsinjects its own default headers,header_matcher(..., strict_match=True)will reject ordinary calls; you have to build and send aPreparedRequestwith overwritten headers to satisfy it.
When to Use / When Not
Use when:
- Your code makes HTTP calls through
requestsand you want fast, deterministic, network-free tests. - You want to assert on outbound request bodies, params, or headers, not just stub responses.
- You want unmatched requests to fail hard rather than silently hit production.
Avoid when:
- The code uses
httpx,aiohttp, or rawurllib3/http.client—responseswon't see those calls. - You want to record and replay real API interactions as fixtures — reach for
vcrpy. - You need library-agnostic mocking at the socket layer —
HTTPrettyor a real fake server fits better. - You're testing async HTTP —
responsesis synchronous,requests-only.
Alternatives
- jamielennox/requests-mock — the other established
requestsmocker; adapter-based likeresponsesbut with a transport-adapter/fixture-centric API. Use it when you prefer itsAdapter/matcher style. - lundberg/respx — mocking for
httpx(sync and async). Use it when your client ishttpx, notrequests. - kevin1024/vcrpy — records real HTTP interactions to YAML "cassettes" and replays them. Use it when you want fixtures captured from a live API rather than hand-written stubs.
- gabrielfalcao/HTTPretty — socket-level interception that works across HTTP libraries. Use it when you must mock a client
responsescan't reach, and can accept a more invasive approach. - pytest-dev/pytest-httpserver — a real local WSGI server for tests. Use it when you want to exercise the actual network path against a controllable endpoint.
History
| Version | Date | Notes |
|---|---|---|
| 0.1.0 | 2013-11-26 | Initial release1. |
| 0.10.0 | 2018-10-18 | Matchers, callbacks, and API maturation era. |
| 0.13.0 | 2021-03-17 | responses.matchers and registry groundwork. |
| 0.14.0 | 2021-09-10 | Param matchers moved under responses.matchers5. |
| 0.17.0 | 2022-01-10 | match_querystring deprecated for explicit query matchers5. |
| 0.20.0 | 2022-03-18 | Top-level assert_all_requests_are_fired/passthru_prefixes/target moved to responses.mock5. |
| 0.25.0 | 2024-02-13 | Ongoing matcher/registry and typing refinements. |
| 0.26.0 | 2026-02-19 | Recent maintenance line; requires requests >= 2.30.03. |
| 0.26.2 | 2026-07-03 | Latest release at time of writing. |
References
- ^ Repository history, getsentry/responses — first commit 2013-11-15,
0.1.0tag 2013-11-26. https://github.com/getsentry/responses/tags - ^ Mechanism (patching
HTTPAdapter.send) described in the library source and README "Basics"/"Custom Registry" sections. https://github.com/getsentry/responses/blob/master/README.rst - ^ README requirements note — "Responses requires Python 3.8 or newer, and requests >= 2.30.0". https://github.com/getsentry/responses/blob/master/README.rst
- ^ README, "Response Registry" (FirstMatchRegistry / OrderedRegistry / custom registry). https://github.com/getsentry/responses/blob/master/README.rst
- ^ README, "Deprecations and Migration Path" table. https://github.com/getsentry/responses/blob/master/README.rst
Tags
python, testing, http-mocking, requests, unit-testing, test-fixtures, mocking, pytest, api-testing, developer-tools