asmcos/requests, a Python-style HTTP client for Go
A golang HTTP client library. Salute to python requests.
At a glance
- What is it?
- The requests library for Go wraps net/http in a Python-requests-shaped API, with package-level Get and Post helpers, header and param arguments, sessions with cookie persistence and multipart uploads. It is a small convenience layer that is explicit about its own sharp edges, including a custom licence and a blunt changelog of recent bug fixes.
- Who is it for?
- The requests library for Go suits a codebase that wants the readability of the Python API without pulling in a large framework, and it suits people who need the same client on the server and on a device where net/http verbosity gets in the way. It does not suit a project that needs a maintained dependency chain with a well-known upstream, because this one is a single maintainer's repository with a custom licence classification and no tagged releases.
- 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 15 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A Go port shaped after the Python original
The github.com/asmcos/requests library exists to give Go programmers the ergonomics of the Python requests library. The project description says it plainly, that it is a Go HTTP client library and a salute to Python requests, and the README calls it an HTTP library that is easy to use and similar to Python requests.
What that means concretely is that the API is built around arguments rather than around a request builder. You pass headers, query parameters, authentication and body data straight into the call, in the style of a function call rather than a struct configuration. The README also lists the feature set as a flat list: set headers, set params, multipart file uploads, sessions with cookie persistence, proxy, authentication, JSON, chunked requests, debug, set timeout, and skipping TLS certificate verification through `SetInsecureSkipVerify`.
The audience is Go developers writing scripts, scrapers and service-to-service calls, where the ergonomics of the standard library's `http.NewRequest` plus `http.Client.Do` sequence are pleasant but verbose. The target is not to replace net/http or to add capabilities it lacks. It is to make a two-line GET feel like a two-line GET.
The repository is a single Go module with the module path github.com/asmcos/requests, a go.mod requiring Go 1.13, and only one external dependency, github.com/davecgh/go-spew v1.1.1, which is a debugging and printing helper. The source lives in a top-level requests.go, with requests_test.go and requests_bugfix_test.go alongside it, an examples/ directory holding get1.go, get_auth.go, get_set_header.go and post1.go, and a docs/ directory.
Package-level Get and Post hide the request object
The simplest call in the library takes a URL and returns a response and an error, with no client to construct first.
package main
import "github.com/asmcos/requests"
func main (){
resp,err := requests.Get("http://www.jeapedu.com")
if err != nil{
return
}
println(resp.Text())
}`requests.Get` is a shortcut that builds a client internally, and the response object exposes the body as a string through `Text()`. Error handling is a normal Go error return, and the sample simply returns on error.
For a POST with form data, the shape changes to a `Datas` map and a `requests.Post` call.
package main
import "github.com/asmcos/requests"
func main (){
data := requests.Datas{
"name":"requests_post_test",
}
resp,_ := requests.Post("https://www.httpbin.org/post",data)
println(resp.Text())
}The documentation shows the server echo for that call, and the form section of the response contains the name value, which confirms the form encoding reaches the server as expected. Note the response also carries a User-Agent of `Go-Requests 0.5` in the shown output, which tells you the library identifies itself to the server.
There is a JSON sibling, `requests.PostJson`, which takes a JSON string rather than a map. The project documentation includes a sample that posts a `{"name":"requests_post_test"}` string, and the echoed response body shows the same form field, which is worth noting because it means the JSON string was sent as a urlencoded form in that example rather than parsed as JSON. The v0.9 changelog also records that `PostJson` used to send extra bytes from the encoder's trailing newline, and that it now uses `Content-Length` and `json.Marshal`.
Headers, params and auth as call arguments
The instance-based form of the API is where the argument style shows. You create a request object with `requests.Requests()`, set things on it, and then pass per-call options as trailing arguments.
req := requests.Requests()
req.Header.Set("accept-encoding", "gzip, deflate, br")
resp,_ := req.Get("http://www.zhanluejia.net.cn",requests.Header{"Referer":"http://www.jeapedu.com"})
println(resp.Text())A per-call header map is merged on top of whatever the request object already holds, and a second example in the README shows a call that takes several header maps at once for cases where headers come from different places. There is a dedicated example file, examples/get_set_header.go, for the same topic.
Query parameters follow the same trailing-argument pattern, using a `requests.Params` map.
p := requests.Params{
"title": "The blog",
"name": "file",
"id": "12345",
}
resp,_ := req.Get("http://www.cpython.org", p)Authentication is a two-element `requests.Auth` value passed the same way, and the README pairs it with a request to the GitHub user endpoint.
req := requests.Requests()
resp,_ := req.Get("https://api.github.com/user",requests.Auth{"asmcos","password...."})
println(resp.Text())One fix in the v0.9 changelog changes how the Host header behaves. Previously a `Header{"Host": "..."}` entry did not change the HTTP Host, and it is now applied to `Request.Host`. That is the kind of detail that matters for virtual host routing and for anyone trying to reproduce a request exactly, and it is one of several listed in that changelog alongside the multipart ordering fix and the resource leak fix for uploaded files and gzip readers.
Timeouts, debug output and reading cookies back
Three smaller capabilities are worth naming because they are the ones people reach for after the basic calls work.
Timeout and debug are both set on the request object before the call.
req := Requests()
req.Debug = 1
// 20 Second
req.SetTimeout(20)
req.Get("http://golang.org")Setting `Debug` to 1 is what turns on the library's request and response debugging output, and `SetTimeout` takes a value in seconds according to the comment in the sample.
Cookies come back off the response, and the documentation shows the returned slice being iterated.
resp,_ = req.Get("https://www.httpbin.org")
coo := resp.Cookies()
// coo is [] *http.Cookies
println("********cookies*******")
for _, c:= range coo{
fmt.Println(c.Name,c.Value)
}The comment in that sample types the slice loosely as `[] *http.Cookies`, but the values iterated are used as `c.Name` and `c.Value`, which is the shape of the standard library's `http.Cookie`. The way to read it is that the response hands you cookie values you can inspect directly.
The other half of the cookie story is the session. The feature list names sessions with cookie persistence as a supported capability, which is the piece that makes login-and-then-scrape flows work, and it pairs with the proxy, authentication, JSON, chunked request and multipart upload features in the same list.
The v0.9 changelog reads like a bug report triage
The most informative document in the repository is the v0.9 changelog section, and it is unusual in how blunt it is. It opens by stating that the release was completed with AI coding assistance, then lists bugs from issues and pull requests one by one.
The substance is worth reading as a compatibility checklist. HTTP/2 retry failed because `Request.GetBody` was not defined, and request bodies are now rewindable through it. `PostJson` sent extra bytes in the body because of chunked encoding and the encoder's trailing newline, and now uses `Content-Length` and `json.Marshal`. Calling `Get` after `Post` on the same client produced a `ContentLength=N with Body length 0` error, and the stale body and `Content-Length` are now cleared between requests. Multipart uploads wrote files before form fields, which broke S3-style POSTs that require `key` first, and form fields are now written before files. Errors were printed with `fmt.Println`, and are now returned only, without extra stdout. `Post` always overwrote `Content-Type`, and the default `application/x-www-form-urlencoded` is now set only when the caller did not set one. `PostJson` ignored URL query `Params`, and query parameters are now applied.
Two more entries are about operations rather than code paths. There was no way to skip TLS verification, so `SetInsecureSkipVerify` was added, and `Proxy()` no longer forces `InsecureSkipVerify` on. Uploaded files and gzip readers were not closed, and both are closed after use.
Reading this list tells you two things about the library's current state. The bug surface is the shared-client and body-handling behaviour, which is where a convenience wrapper over net/http tends to go wrong. And the fixes are recent enough that a version of the library older than v0.9 will behave differently in ways that are not obvious from the API.
The licence and the release situation need checking
Two facts about how this project is packaged are worth putting next to each other, because both affect adoption decisions.
First, the licence. The repository's licence is classified as a custom type that GitHub cannot classify, and the terms live in the LICENSE file at the top level of the tree. The README carries a badge image pointing to an Apache 2.0 licence graphic and linking to the LICENSE file, and the badge is the only in-repository statement of the terms. If your organisation needs to know exactly what you are licensing, the answer is to read LICENSE directly rather than to infer it from a badge.
Second, the packaging. The repository has no GitHub releases, so there is no tagged artifact to install and no changelog attached to a version page, even though the README carries a v0.9 changelog section as text. Installation is therefore a `go get` of the default branch.
go get -u github.com/asmcos/requestsThe `-u` flag pulls the latest version of the dependency, which for a module with no tags means the tip of the default branch, master. That is worth pausing on. In a normal Go project, a tagged release and a go.sum entry give you a reproducible dependency, and a `go get -u` in a build script is unusual for that reason. Here it means the module you build against can change underneath you, and the changelog shows that the body-handling behaviour of the v0.9 line did change in ways that affect request semantics.
The module also declares Go 1.13, which is old enough that the version constraint will not stop you from building with a much newer toolchain, and the single external dependency, go-spew, is a small print-debugging helper rather than a framework.
Where the standard library is the better answer
The comparison that matters here is not with another Go HTTP wrapper, it is with not adding a dependency at all. Go's net/http has had a client with `Get`, `Post` and `Do` for a long time, and it has context-aware requests, connection pooling, cookie jars, redirect policies and per-request client options. Everything the requests library offers in a shorter form is expressible there, at the cost of a couple more lines and a struct you have to build.
The difference in approach is that net/http exposes transport configuration explicitly, while this library folds it into method arguments. That is a real ergonomic win for scripts and for call sites where the request is simple, and a real loss when you need to control timeouts per phase, cancel a request, or reuse a client with a specific transport across calls. The library does have `SetTimeout` and sessions, but the configuration surface is a small fixed set of knobs rather than the full `http.Client` and `http.Transport` model.
There is a second practical difference, which is dependency risk in a security-sensitive position. A convenience library that owns request body construction, header merging and multipart encoding is exactly the place where subtle bugs live, and the v0.9 list is a catalogue of them. A team that has already had a security review of its HTTP layer, or one that is writing a large service rather than a script, may prefer to keep that layer inside the standard library where the audit surface is smaller and the upstream is the Go project itself.
For a scraper, a one-off integration script or a small internal tool, the trade flips the other way. The library saves real code, its API is easy to read, and the maintainer clearly cares about correctness given how detailed that changelog is.
Editorial conclusion
The requests library for Go suits a codebase that wants the readability of the Python API without pulling in a large framework, and it suits people who need the same client on the server and on a device where net/http verbosity gets in the way. It does not suit a project that needs a maintained dependency chain with a well-known upstream, because this one is a single maintainer's repository with a custom licence classification and no tagged releases. Verify first that the licence file matches what your organisation expects, because the licence type is one GitHub cannot classify, then confirm that the request body helpers behave the way your code assumes, since the v0.9 changelog lists several body and Content-Length bugs that were only fixed recently.
Frequently asked questions
How do I install the asmcos/requests Go library?
The README gives a single command, go get -u github.com/asmcos/requests, and the module path in go.mod matches that import path. The go.mod declares Go 1.13 and requires only github.com/davecgh/go-spew v1.1.1.
How do I POST form data with the requests Go library?
Build a requests.Datas map with your fields and pass it to requests.Post, as the README sample does with a name field posted to the httpbin endpoint. The server echo in the documentation shows the value arriving in the form section of the response.
How do I set headers and query parameters in asmcos/requests?
You can set them on the request object with req.Header.Set, or pass them per call as trailing arguments: a requests.Header map for headers and a requests.Params map for query parameters, both shown in the README examples.
Can I skip TLS certificate verification with the requests Go library?
Yes. The feature list names SetInsecureSkipVerify, and the v0.9 changelog records that it was added because there was no way to skip TLS verification, and that Proxy no longer forces InsecureSkipVerify on.
What licence does the asmcos/requests library use?
The licence is a custom type that GitHub cannot classify, with the actual terms in the LICENSE file at the top level of the repository. The README carries an Apache 2.0 licence badge that links to that same file, so read LICENSE directly for the authoritative terms.
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/asmcos-requests)Was this useful?