# httr: a friendly curl wrapper for R that has been superseded by httr2

> httr wraps the curl package in an interface tailored to web APIs, giving R users verb functions, a standard response object, config helpers and OAuth 1.0 and 2.0 support. It is now marked superseded, with only the changes needed to keep it on CRAN, so the real decision is whether to adopt it or start on httr2.

**r-lib/httr** — httr: a friendly http package for R

- Repository: https://github.com/r-lib/httr
- Website: https://httr.r-lib.org
- Stars: 983 · Forks: 1,955
- Language: R
- License: NOASSERTION
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/r-lib-httr

## httr is superseded, and that changes the adoption question

The most important fact about httr sits at the top of its README, before any feature description. The project carries a lifecycle badge marked superseded, and the status section states that only changes necessary to keep it on CRAN will be made. It recommends using httr2 instead.

That reframes what this article can be. httr is not a package to evaluate for a new project. It is a package to evaluate for the project you already have. Teams running scripts that call GET() and POST() against APIs in production need to know whether the package will keep working, whether security fixes will land, and how long the code will run on a machine where nobody can install httr2 without rewriting everything.

The rest of the article looks at what the package actually does, because that determines how painful a migration would be. The short version is that the surface is small and the concepts are standard, which is good news for anyone planning to move.

The historical credit is also worth recording, since the project itself makes the point: httr would not be possible without the work of the authors of curl and libcurl, and the design was inspired by HTTP libraries in other languages such as Resty, Requests and httparty.

## Verb functions and one response object for every call

The aim of httr is stated as providing a wrapper for the curl package, customised to the demands of modern web APIs. The interface starts with functions for the most important HTTP verbs: GET(), HEAD(), PATCH(), PUT(), DELETE() and POST(). Nothing exotic, and that is the point.

Every request returns a standard response object that captures the HTTP status line, headers and body, along with other useful information. Because the object shape is the same for every verb and every request, code that inspects a result does not have to care whether the call was a GET or a POST.

The body is read through content(), and the same function handles three representations. With as = "raw" you get a raw vector, with as = "text" a character vector, and with as = "parsed" the content is parsed into an R object. The documentation states that parsed content currently covers html, xml, json, png and jpeg. That list is narrower than people often assume, so a JSON API is comfortable, while a CSV or a protobuf response would need manual handling.

Errors are a separate, explicit step. You can convert HTTP errors into R errors with stop_for_status(), which means a 404 does not silently look like an empty body. For scripts that run unattended, that distinction decides whether a failure is visible.

## Connection sharing, cookie persistence and certificate handling

Three behaviours are handled underneath the verb functions, and they are the reason httr is more than a thin call wrapper.

Connection sharing works across requests to the same website. By default, curl handles are managed automatically, which means repeated calls to one host reuse a connection instead of opening a new one each time. For a script that hits an API endpoint fifty times, that difference is felt in both time and in how often the server sees you.

Cookies are maintained across requests, so a session established by one call is visible to the next. This is what makes login flows work without the caller implementing a cookie jar.

Certificate handling is the third piece: an up-to-date root-level SSL certificate store is used. For R users on machines with an outdated or missing trust store, this removes a class of confusing TLS failures that have nothing to do with the code being written.

None of this is visible in the verb signatures, which is exactly the design goal. The functions look like HTTP verbs and the transport concerns live underneath.

## Config functions and OAuth token helpers

Requests are modified through config functions rather than by rewriting the underlying curl options. The documented set is set_cookies(), add_headers(), authenticate(), use_proxy(), verbose(), timeout(), content_type(), accept() and progress().

That set covers the adjustments an API client usually needs. Headers and cookies, authentication, a proxy for a corporate network, a timeout so a hung request does not block a job forever, a declared content type and accept header for a REST endpoint, verbosity for debugging, and a progress indicator for a slow download.

OAuth support is built in for both versions of the protocol, through oauth1.0_token() and oauth2.0_token(). The documentation notes that OAuth credentials are automatically cached within a project, so tokens are not re-fetched on every run inside the same project directory.

The demo directory is the practical evidence of what the OAuth support has been exercised against. The README describes eight demos, four for OAuth 1.0 covering twitter, vimeo, withings and yahoo, and four for OAuth 2.0 covering facebook, github, google and linkedin. The files present in the repository go slightly further, with demos for azure, reddit, vimeo and yelp in the 2.0 set, plus a service-account example. A demo directory this size is a reasonable signal about which providers have actually been used with these helpers.

## Installing httr from CRAN or from a GitHub checkout

There are two supported ways to get the package, and the difference matters if you are pinning versions.

From CRAN, the released version is installed with the standard R command:

```R
install.packages("httr")
```

From GitHub, the development version is installed through pak, with the package name given as the repository slug:

```R
# install.packages("pak")
pak::pak("r-lib/httr")
```

The commented line is there because pak itself has to be present first. Installing from GitHub gives you the current state of the main branch rather than the CRAN snapshot, and for a superseded package that distinction is smaller than it sounds, since the branch is not where new features are being added.

A first call after installation looks like any other HTTP request. A GET against an endpoint returns the response object, content() reads the body as text or parsed content, and stop_for_status() turns an HTTP error into an R error when the script should not continue.

For teams reproducing an analysis, pinning to the CRAN version is the more predictable choice, since the GitHub path moves as the branch moves.

## What superseding means for a production dependency

Superseded does not mean broken, but it does define what kind of maintenance you are buying. The rule stated by the project is that only changes necessary to keep it on CRAN will be made. That covers dependency updates, R compatibility fixes and anything CRAN policy requires, and it rules out new features.

The release history shows the shape of that. v1.4.7 was published on 2023-08-15, v1.4.8 on 2026-02-13 and v1.4.9 on 2026-09-01, and the last push to the repository was on 2026-09-01. So the package still moves, and the recent movement is faster than the 2023 gap suggests, but the movement is maintenance rather than development.

For a production script this has two consequences. The first is security exposure: a package that receives no feature work also receives no feature-adjacent fixes, so an HTTP client that is only patched for CRAN compliance is not being improved for new TLS behaviour or new protocol details. The second is dependency risk in the other direction, since the curl package and libcurl underneath httr are maintained elsewhere, and the upstream packages can change behaviour that httr does not adjust for.

None of this makes httr unsafe to keep. It makes it a package to plan around rather than to build on.

## The licence is custom, and the credit chain goes deeper than httr

The licence situation deserves a look before you copy code out of the package. The repository listing for the project shows a custom licence that GitHub cannot classify, and the licence is recorded in a LICENSE file alongside a LICENSE.md file, with the DESCRIPTION file at the root of the package. The r-lib projects are typically MIT, but the recorded status for this repository is a custom licence, so read the file rather than assuming the norm.

That matters most for a package people often copy snippets from. If you lift an httr configuration or an OAuth demo into a closed-source product, the terms of that licence are what apply, and they should be checked rather than assumed.

The dependency chain runs deeper than the package itself. httr wraps the curl package, which wraps libcurl, and the project states plainly that it would not be possible without the hard work of the authors of curl and libcurl. The curl handles that httr manages automatically come from that layer, so the certificate store behaviour and the connection sharing are really properties of the transport underneath rather than of httr's own code.

The repository also carries the usual r-lib scaffolding: a NEWS.md file for release notes, vignettes, a revdep directory for reverse dependency checks, an R-CMD-check workflow, and a Contributor Code of Conduct that contributors agree to.

## Conclusion

Adopt httr only when you are maintaining an existing R codebase that already depends on it, or when you need the OAuth token helpers it ships in a form you cannot yet move. For anything new, start on httr2, since httr receives no features and only the changes needed to keep it on CRAN. Before committing either way, check whether your existing scripts already call content(), stop_for_status(), add_headers() or oauth2.0_token(), and read the licence file, since the package carries a custom licence that GitHub cannot classify rather than a standard MIT or GPL text.

## FAQ

### Is httr deprecated or still maintained?

httr is marked superseded. The project states that only changes necessary to keep it on CRAN will be made, and it recommends httr2 for new work. The last push was on 2026-09-01, and v1.4.9 was published on the same day.

### How do I install httr in R?

From CRAN, use install.packages("httr"). For the development version from GitHub, install pak first and then run pak::pak("r-lib/httr"), which is the form shown in the project README.

### How do I read the body of an httr response?

Use content() on the response. It returns a raw vector with as = "raw", a character vector with as = "text", or a parsed R object with as = "parsed", where parsing currently covers html, xml, json, png and jpeg. Call stop_for_status() to turn HTTP errors into R errors.

### Does httr support OAuth?

Yes, through oauth1.0_token() for OAuth 1.0 and oauth2.0_token() for OAuth 2.0. The demo directory contains eight demos described in the README, four for each protocol, and OAuth credentials are cached automatically within a project.

### What licence does httr use?

The repository records a custom licence that GitHub cannot classify, with the terms in the LICENSE file and a LICENSE.md alongside it. Check that file directly before reusing code from the package in a product, rather than assuming a standard open source licence.

## Sources

- [Issues](https://github.com/r-lib/httr/issues)
- [Project website](https://httr.r-lib.org)
- [README](https://github.com/r-lib/httr/blob/main/README.md)
- [Releases](https://github.com/r-lib/httr/releases)
- [r-lib/httr on GitHub](https://github.com/r-lib/httr)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/r-lib-httr
