Requests speaks HTTP/1.1, honours your .netrc, and ships an empty extra called security
GitHub describes it as A simple, yet elegant, HTTP library.. The repository metadata lists Python as its primary language. The metadata lists the Apache-2.0 license. This article stays within the project description and details documented in the GitHub repository README.
At a glance
- What is it?
- The Python HTTP library behind a reported four million dependent repositories, with four runtime dependencies and a ceiling on urllib3 that keeps it off version 3. SOCKS support is an optional extra, free-threaded Python is marked Beta, and the make target that validates the readme still checks reStructuredText filenames the repository no longer has.
- Who is it for?
- Adopt Requests when you want the conventional HTTP client in Python and do not need protocol versions beyond HTTP/1.1, because the ergonomics around query strings, form encoding, sessions and cookies are the reason it became the default, and four runtime dependencies is a genuinely small surface to audit. Do not adopt it expecting HTTP/2 or HTTP/3, since the readme describes sending HTTP/1.1 requests and nothing further.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The readme describes sending HTTP/1.1 requests, and nothing beyond
Start with the protocol, because it is the one hard limit in an otherwise frictionless library. The description says Requests allows you to send HTTP/1.1 requests extremely easily, and then spends its energy on ergonomics instead: no manual query strings, no manual form encoding for PUT and POST, with a pointer to just use the json method nowadays. There is no mention anywhere of HTTP/2 or HTTP/3, no multiplexing, and no async story. The example in the readme makes the shape concrete, showing a GET against a basic-auth endpoint with a tuple for auth, then reading the status code, a response header, the detected encoding, the text and the parsed JSON off the same object. The consequence is that protocol-level progress is not something you get here. If you need connection multiplexing or a newer protocol, you are going to reach for the underlying transport directly, and at that point the conveniences that justified the dependency are behind you.
SOCKS support is a feature you have to install, with one release excluded by name
The feature list advertises SOCKS proxy support alongside keep-alive and connection pooling, streaming downloads and chunked requests, and that promise is real but conditional. The project manifest declares it as an optional dependency group containing a single requirement on the SOCKS library with a floor and an explicit exclusion of one exact release, written as a not-equal constraint on 1.5.7. So a plain install of the package gives you no SOCKS support at all, and a resolver has to skip that specific version to satisfy the requirement. The same manifest carries a second optional group that opts into a different charset detection library on Python 3, which is the other place where the default behaviour is not what the feature list implies. The consequence is small but it is the kind of small thing that costs an afternoon: the feature list describes the library at its fullest, and the default install is narrower, with the difference documented in a manifest field rather than in the readme.
There is an optional dependency group called security and it is empty
Read the optional dependency groups in the project manifest and one of them is named security and contains no requirements at all. It is an empty list, which means the extra installs successfully and changes nothing. Nothing in the readme points at it, so this is not a documented feature you are failing to use; it is a placeholder or a leftover, and it is the kind of name that causes real confusion when someone reaches for it. The plausible reason for reaching for it is a supply-chain worry, which is a reasonable worry about a package the readme says is depended upon by more than four million repositories and downloaded around three hundred million times a week according to GitHub. The consequence is that a security-minded reader looking for a hardened install path finds a named extra that installs nothing and reports success. Read the four runtime dependencies and their version ceilings instead, which is where the actual surface is.
It honours your .netrc automatically, without you passing anything
One entry in the feature list is easy to skim past and worth not skimming past: automatic honouring of the netrc file. That is the plain-text credentials file in a user's home directory that maps a machine to a login and password for remote tools. Requests will consult it and attach credentials to a request when the host matches, without an auth argument and without any indication in your code that it did. On a workstation this is the convenience you want, and it is the reason the entry is in a feature list rather than a caveat. In continuous integration it inverts. A credentials file baked into a build image, or mounted into a runner, becomes a source of authentication on outbound requests you did not intend to authenticate, and the request succeeds in a way that looks like an authentication bug elsewhere. The consequence is that in an automated environment, know whether a netrc is present before you debug anything about a 401.
A plain clone can fail outright on a bad commit timestamp
The readme warns that when you clone the repository you may need to add a specific configuration flag to avoid an error about a bad commit timestamp, and it links an issue for background. The flag sets a fetch setting to ignore that class of problem, and the readme also gives the alternative of applying the same setting to your global git configuration.
git clone -c fetch.fsck.badTimezone=ignore https://github.com/psf/requests.gitThe consequence is that this is the one widely used Python package whose clone is not a plain clone, and the failure looks alarming because it arrives as a filesystem consistency error rather than as a network or permission problem. Most people meet it once, read the error, find nothing, and conclude their git is broken. The documented workarounds are both legitimate, and the global setting is the better of the two if you work on this repository regularly, though it does quietly relax a check for every repository you touch. Either way it is a property of the history, not of the working tree, so it will not be fixed by a fresh clone.
The readme guard checks reStructuredText filenames the repository no longer has
The Makefile carries a target whose job is to validate the readme's markup, and it is looking for the wrong files. The target runs a documentation check in strict mode and then echoes either that the files are ok or that the markup is invalid, and it names them with a reStructuredText extension. The repository tree contains a Markdown readme and a Markdown history file, and the only reStructuredText document still present is the authors file. So the guard either passes vacuously or is validating a document nobody edits any more, while the files that actually need checking go unchecked. The rest of the Makefile is in better shape and worth reading as a description of how the project works: a target that installs development requirements, a plain test target, a continuous integration target that additionally writes a JUnit report, a coverage target pointed at the source directory with both a terminal and an XML report, and a publish target that builds into a throwaway virtual environment.
Publishing skips versions that already exist, and free threading is Beta
Two small details round out the picture, and both are the kind you only find by reading the build files. The publish target uploads built distributions with a skip-existing flag, which means a version that is already on the package index is passed over rather than reported as a conflict. That is convenient for a re-run after a network failure and dangerous for a mistake, because re-tagging a version that already shipped produces a successful looking release that changed nothing. The second detail is in the project classifiers, which list supported interpreter versions from 3.10 through 3.15, cover both CPython and PyPy, and carry a free-threading classifier at level two, meaning Beta. The consequence for the second is that a no-GIL interpreter is an acknowledged configuration but not a settled one, and the setup script's own version guard stops anything below 3.10 before the build even starts, so the floor is enforced in two places.
Editorial conclusion
Adopt Requests when you want the conventional HTTP client in Python and do not need protocol versions beyond HTTP/1.1, because the ergonomics around query strings, form encoding, sessions and cookies are the reason it became the default, and four runtime dependencies is a genuinely small surface to audit. Do not adopt it expecting HTTP/2 or HTTP/3, since the readme describes sending HTTP/1.1 requests and nothing further. Three things to know before you rely on it. It reads your .netrc without being asked, so a stray credentials file can attach authentication to a request without you passing anything. SOCKS support needs an extra install and excludes one named release. And the free-threaded build is classified Beta, so treat a no-GIL deployment as new ground rather than a supported configuration.
Frequently asked questions
How do I install requests in Python?
From the package index with a single pip command, which the readme shows as python -m pip install requests. Requests officially supports Python 3.10 and newer, and the project classifier set covers versions through 3.15 on both CPython and PyPy.
How do I use requests.get in Python?
Import the module and call get with a URL, optionally passing an auth tuple, then read the response object. The readme example fetches a basic-auth endpoint and then reads the status code, a content-type header, the detected encoding, the raw text and the parsed JSON off that one object.
Does requests support SOCKS proxies out of the box?
Not from a default install. SOCKS proxy support is listed as a feature but is declared as an optional dependency group requiring the SOCKS library, with one exact release excluded by a not-equal constraint. You have to install that extra to get the behaviour the feature list describes.
Why does cloning the requests repository fail for me?
The readme says a clone may need a fetch configuration flag to avoid an error about a bad commit timestamp, and it links an issue for background. The documented alternative is applying the same setting to your global git configuration, which relaxes that check for every repository you work with.
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/psf-requests)