GoRequest -- Simplified HTTP client ( inspired by famous SuperAgent lib in Node.js )


"Shooting Requests like a Machine Gun" - Gopher

Sending request has never been as fun nor easier than this. It comes with lots of features:

  • Get/Post/Put/Head/Delete/Patch/Options
  • Set - simple header setting
  • JSON - made it simple with JSON string as a parameter
  • Multipart-Support - send data and files as multipart request
  • Proxy - sending request via proxy
  • Timeout - setting timeout for a request
  • TLSClientConfig - taking control over tls where at least you can disable security check for https
  • RedirectPolicy
  • Cookie - setting cookies for your request
  • CookieJar - automatic in-memory cookiejar
  • BasicAuth - setting basic authentication header
  • more to come..


$ go get


See Go Doc or Go Walker for usage and details.


Drone Build Status Travis Build Status

Why should you use GoRequest?

GoRequest makes thing much more simple for you, making http client more awesome and fun like SuperAgent + golang style usage.

This is what you normally do for a simple GET without GoRequest:

resp, err := http.Get("")

With GoRequest:

request := gorequest.New()
resp, body, errs := request.Get("").End()

Or below if you don't want to reuse it for other requests.

resp, body, errs := gorequest.New().Get("").End()

How about getting control over HTTP client headers, redirect policy, and etc. Things can quickly get more complicated in golang. You need to create a Client, set headers in a different command, ... just to do only one GET

client := &http.Client{
  CheckRedirect: redirectPolicyFunc,

req, err := http.NewRequest("GET", "", nil)

req.Header.Add("If-None-Match", `W/"wyzzy"`)
resp, err := client.Do(req)

Why make things ugly while you can just do it as follows:

request := gorequest.New()
resp, body, errs := request.Get("").
  Set("If-None-Match", `W/"wyzzy"`).

DELETE, HEAD, POST, PUT, PATCH are now supported and can be used in the same way as GET:

request := gorequest.New()
resp, body, errs := request.Post("").End()
// PUT -> request.Put("").End()
// DELETE -> request.Delete("").End()
// HEAD -> request.Head("").End()
// ANYTHING -> request.CustomMethod("TRACE", "").End()

For a JSON POST with standard libraries, you might need to marshal map data structure to json format, set headers to 'application/json' (and other headers if you need to) and declare http.Client. So, your code becomes longer and harder to maintain:

m := map[string]interface{}{
  "name": "backy",
  "species": "dog",
mJson, _ := json.Marshal(m)
contentReader := bytes.NewReader(mJson)
req, _ := http.NewRequest("POST", "", contentReader)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Notes","GoRequest is coming!")
client := &http.Client{}
resp, _ := client.Do(req)

Compared to our GoRequest version, JSON is for sure a default. So, it turns out to be just one simple line!:

request := gorequest.New()
resp, body, errs := request.Post("").
  Set("Notes","gorequst is coming!").
  Send(`{"name":"backy", "species":"dog"}`).

Moreover, it also supports struct type. So, you can have a fun Mix & Match sending the different data types for your request:

type BrowserVersionSupport struct {
  Chrome string
  Firefox string
ver := BrowserVersionSupport{ Chrome: "37.0.2041.6", Firefox: "30.0" }
request := gorequest.New()
resp, body, errs := request.Post("").

Not only for Send() but Query() is also supported. Just give it a try! :)


Moreover, GoRequest also supports callback function. This gives you much more flexibility on using it. You can use it any way to match your own style! Let's see a bit of callback example:

func printStatus(resp gorequest.Response, body string, errs []error){


You can specify the content-type of the request to type multipart to send all data as multipart/form-data. This feature also allows you to send (multiple) files! Check the examples below!


The SendFile function accepts strings as path to a file, []byte slice or even a os.File! You can also combine them to send multiple files with either custom name and/or custom fieldname:

          f, _ := filepath.Abs("./file2.txt")
bytesOfFile, _ := ioutil.ReadFile(f)

  SendFile(bytesOfFile, "file2.txt", "my_file_fieldname").

Check the docs for SendFile to get more information about the types of arguments.


In the case when you are behind proxy, GoRequest can handle it easily with Proxy func:

request := gorequest.New().Proxy("http://proxy:999")
resp, body, errs := request.Get("").End()
// To reuse same client with no_proxy, use empty string:
resp, body, errs = request.Proxy("").Get("").End()

Basic Authentication

To add a basic authentication header:

request := gorequest.New().SetBasicAuth("username", "password")
resp, body, errs := request.Get("").End()


Timeout can be set in any time duration using time package:

request := gorequest.New().Timeout(2*time.Millisecond)
resp, body, errs:= request.Get("").End()

Timeout func defines both dial + read/write timeout to the specified time parameter.


Thanks to @jaytaylor, we now have EndBytes to use when you want the body as bytes.

The callbacks work the same way as with End, except that a byte array is used instead of a string.

resp, bodyBytes, errs := gorequest.New().Get("").EndBytes()


We now have EndStruct to use when you want the body as struct.

The callbacks work the same way as with End, except that a struct is used instead of a string.

Supposing the URL returns the body {"hey":"you"}

heyYou struct {
  Hey string `json:"hey"`

var heyYou heyYou

resp, _, errs := gorequest.New().Get("").EndStruct(&heyYou)


Supposing you need retry 3 times, with 5 seconds between each attempt when gets a BadRequest or a InternalServerError

request := gorequest.New()
resp, body, errs := request.Get("").
                    Retry(3, 5 * time.Second, http.StatusBadRequest, http.StatusInternalServerError).

Handling Redirects

Redirects can be handled with RedirectPolicy which behaves similarly to net/http Client's CheckRedirect function. Simply specify a function which takes the Request about to be made and a slice of previous Requests in order of oldest first. When this function returns an error, the Request is not made.

For example to redirect only to https endpoints:

request := gorequest.New()
resp, body, errs := request.Get("").
                    RedirectPolicy(func(req Request, via []*Request) error {
                      if req.URL.Scheme != "https" {
                        return http.ErrUseLastResponse


You can reuse settings of a Request by cloning it before making any requests. This can be useful if you wish to re-use the SuperAgent across multiple requests without worrying about concurrency or having too many Transports being created.

Clones will copy the same settings (headers, query, etc..), but will only shallow copy any "Data" given to it. They will also share the same Transport and http.Client.

baseRequest := gorequest.New()
// apply anything you want to these settings. Eg:
baseRequest.Timeout(10 * time.Millisecond).
  BasicAuth("user", "password")

// then reuse the base request elsewhere, cloning before modifying or using it.
resp, body, errs := baseRequest.Clone().Get("").End()


For debugging, GoRequest leverages httputil to dump details of every request/response. (Thanks to @dafang)

You can just use SetDebug or environment variable GOREQUEST_DEBUG=0|1 to enable/disable debug mode and SetLogger to set your own choice of logger.

Thanks to @QuentinPerez, we can see even how gorequest is compared to CURL by using SetCurlCommand.


As the underlying gorequest is based on http.Client in most use cases, gorequest.New() should be called once and reuse gorequest as much as possible.

Contributing to GoRequest:

If you find any improvement or issue you want to fix, feel free to send me a pull request with testing.

Thanks to all contributors thus far:


Also, co-maintainer is needed here. If anyone is interested, please email me (parnurzeal at


  • Renee French - the creator of Gopher mascot
  • Wisi Mongkhonsrisawat for providing an awesome GoRequest's Gopher image :)


GoRequest is MIT License.

Expand ▾ Collapse ▴



    Package gorequest inspired by Nodejs SuperAgent provides easy-way to write http client



    View Source
    const (
    	POST    = "POST"
    	GET     = "GET"
    	HEAD    = "HEAD"
    	PUT     = "PUT"
    	PATCH   = "PATCH"

      HTTP methods we support

      View Source
      const (
      	TypeJSON       = "json"
      	TypeXML        = "xml"
      	TypeUrlencoded = "urlencoded"
      	TypeForm       = "form"
      	TypeFormData   = "form-data"
      	TypeHTML       = "html"
      	TypeText       = "text"
      	TypeMultipart  = "multipart"

        Types we support.


        View Source
        var DisableTransportSwap = false
        View Source
        var Types = map[string]string{
        	TypeJSON:       "application/json",
        	TypeXML:        "application/xml",
        	TypeForm:       "application/x-www-form-urlencoded",
        	TypeFormData:   "application/x-www-form-urlencoded",
        	TypeUrlencoded: "application/x-www-form-urlencoded",
        	TypeHTML:       "text/html",
        	TypeText:       "text/plain",
        	TypeMultipart:  "multipart/form-data",


        This section is empty.


        type File

        type File struct {
        	Filename  string
        	Fieldname string
        	Data      []byte

        type Logger

        type Logger interface {
        	Printf(format string, v ...interface{})
        	Println(v ...interface{})

        type Request

        type Request *http.Request

        type Response

        type Response *http.Response

        type SuperAgent

        type SuperAgent struct {
        	Url               string
        	Method            string
        	Header            http.Header
        	TargetType        string
        	ForceType         string
        	Data              map[string]interface{}
        	SliceData         []interface{}
        	FormData          url.Values
        	QueryData         url.Values
        	FileData          []File
        	BounceToRawString bool
        	RawString         string
        	Client            *http.Client
        	Transport         *http.Transport
        	Cookies           []*http.Cookie
        	Errors            []error
        	BasicAuth         struct{ Username, Password string }
        	Debug             bool
        	CurlCommand       bool
        	Retryable            superAgentRetryable
        	DoNotClearSuperAgent bool
        	// contains filtered or unexported fields

          A SuperAgent is a object storing all request data for client.

          func New

          func New() *SuperAgent

            Used to create a new SuperAgent object.

            func (*SuperAgent) AddCookie

            func (s *SuperAgent) AddCookie(c *http.Cookie) *SuperAgent

              AddCookie adds a cookie to the request. The behavior is the same as AddCookie on Request from net/http

              func (*SuperAgent) AddCookies

              func (s *SuperAgent) AddCookies(cookies []*http.Cookie) *SuperAgent

                AddCookies is a convenient method to add multiple cookies

                func (*SuperAgent) AppendHeader

                func (s *SuperAgent) AppendHeader(param string, value string) *SuperAgent

                  AppendHeader is used for setting header fileds with multiple values, Example. To set `Accept` as `application/json, text/plain`

                    AppendHeader("Accept", "application/json").
                    AppendHeader("Accept", "text/plain").

                  func (*SuperAgent) AsCurlCommand

                  func (s *SuperAgent) AsCurlCommand() (string, error)

                    AsCurlCommand returns a string representing the runnable `curl' command version of the request.

                    func (*SuperAgent) ClearSuperAgent

                    func (s *SuperAgent) ClearSuperAgent()

                      Clear SuperAgent data for another new request.

                      func (*SuperAgent) Clone

                      func (s *SuperAgent) Clone() *SuperAgent

                        Returns a copy of this superagent. Useful if you want to reuse the client/settings concurrently. Note: This does a shallow copy of the parent. So you will need to be careful of Data provided Note: It also directly re-uses the client and transport. If you modify the Timeout, or RedirectPolicy on a clone, the clone will have a new http.client. It is recommended that the base request set your timeout and redirect polices, and no modification of the client or transport happen after cloning. Note: DoNotClearSuperAgent is forced to "true" after Clone

                        func (*SuperAgent) CustomMethod

                        func (s *SuperAgent) CustomMethod(method, targetUrl string) *SuperAgent

                          Just a wrapper to initialize SuperAgent instance by method string

                          func (*SuperAgent) Delete

                          func (s *SuperAgent) Delete(targetUrl string) *SuperAgent

                          func (*SuperAgent) End

                          func (s *SuperAgent) End(callback ...func(response Response, body string, errs []error)) (Response, string, []error)

                            End is the most important function that you need to call when ending the chain. The request won't proceed without calling it. End function returns Response which matchs the structure of Response type in Golang's http package (but without Body data). The body data itself returns as a string in a 2nd return value. Lastly but worth noticing, error array (NOTE: not just single error value) is returned as a 3rd value and nil otherwise.

                            For example:

                            resp, body, errs := gorequest.New().Get("").End()
                            if errs != nil {
                            fmt.Println(resp, body)

                            Moreover, End function also supports callback which you can put as a parameter. This extends the flexibility and makes GoRequest fun and clean! You can use GoRequest in whatever style you love!

                            For example:

                            func printBody(resp gorequest.Response, body string, errs []error){

                            func (*SuperAgent) EndBytes

                            func (s *SuperAgent) EndBytes(callback ...func(response Response, body []byte, errs []error)) (Response, []byte, []error)

                              EndBytes should be used when you want the body as bytes. The callbacks work the same way as with `End`, except that a byte array is used instead of a string.

                              func (*SuperAgent) EndStruct

                              func (s *SuperAgent) EndStruct(v interface{}, callback ...func(response Response, v interface{}, body []byte, errs []error)) (Response, []byte, []error)

                                EndStruct should be used when you want the body as a struct. The callbacks work the same way as with `End`, except that a struct is used instead of a string.

                                func (*SuperAgent) Get

                                func (s *SuperAgent) Get(targetUrl string) *SuperAgent

                                func (*SuperAgent) Head

                                func (s *SuperAgent) Head(targetUrl string) *SuperAgent

                                func (*SuperAgent) MakeRequest

                                func (s *SuperAgent) MakeRequest() (*http.Request, error)

                                func (*SuperAgent) Options

                                func (s *SuperAgent) Options(targetUrl string) *SuperAgent

                                func (*SuperAgent) Param

                                func (s *SuperAgent) Param(key string, value string) *SuperAgent

                                  As Go conventions accepts ; as a synonym for &. ( Thus, Query won't accept ; in a querystring if we provide something like fields=f1;f2;f3 This Param is then created as an alternative method to solve this.

                                  func (*SuperAgent) Patch

                                  func (s *SuperAgent) Patch(targetUrl string) *SuperAgent

                                  func (*SuperAgent) Post

                                  func (s *SuperAgent) Post(targetUrl string) *SuperAgent

                                  func (*SuperAgent) Proxy

                                  func (s *SuperAgent) Proxy(proxyUrl string) *SuperAgent

                                    Proxy function accepts a proxy url string to setup proxy url for any request. It provides a convenience way to setup proxy which have advantages over usual old ways. One example is you might try to set `http_proxy` environment. This means you are setting proxy up for all the requests. You will not be able to send different request with different proxy unless you change your `http_proxy` environment again. Another example is using Golang proxy setting. This is normal prefer way to do but too verbase compared to GoRequest's Proxy:


                                    To set no_proxy, just put empty string to Proxy func:


                                    func (*SuperAgent) Put

                                    func (s *SuperAgent) Put(targetUrl string) *SuperAgent

                                    func (*SuperAgent) Query

                                    func (s *SuperAgent) Query(content interface{}) *SuperAgent

                                      Query function accepts either json string or strings which will form a query-string in url of GET method or body of POST method. For example, making "/search?query=bicycle&size=50x50&weight=20kg" using GET method:

                                        Query(`{ query: 'bicycle' }`).
                                        Query(`{ size: '50x50' }`).
                                        Query(`{ weight: '20kg' }`).

                                      Or you can put multiple json values:

                                        Query(`{ query: 'bicycle', size: '50x50', weight: '20kg' }`).

                                      Strings are also acceptable:


                                      Or even Mixed! :)

                                        Query(`{ size: '50x50', weight:'20kg' }`).

                                      func (*SuperAgent) RedirectPolicy

                                      func (s *SuperAgent) RedirectPolicy(policy func(req Request, via []Request) error) *SuperAgent

                                        RedirectPolicy accepts a function to define how to handle redirects. If the policy function returns an error, the next Request is not made and the previous request is returned.

                                        The policy function's arguments are the Request about to be made and the past requests in order of oldest first.

                                        func (*SuperAgent) Retry

                                        func (s *SuperAgent) Retry(retryerCount int, retryerTime time.Duration, statusCode *SuperAgent


                                          Retry(3, 5 * time.seconds, http.StatusBadRequest, http.StatusInternalServerError).

                                          func (*SuperAgent) Send

                                          func (s *SuperAgent) Send(content interface{}) *SuperAgent

                                            Send function accepts either json string or query strings which is usually used to assign data to POST or PUT method. Without specifying any type, if you give Send with json data, you are doing requesting in json format:

                                              Send(`{ query: 'sushi' }`).

                                            While if you use at least one of querystring, GoRequest understands and automatically set the Content-Type to `application/x-www-form-urlencoded`


                                            So, if you want to strictly send json format, you need to use Type func to set it as `json` (Please see more details in Type function). You can also do multiple chain of Send:

                                              Send(`{ wheel: '4'}`).

                                            From v0.2.0, Send function provide another convenience way to work with Struct type. You can mix and match it with json and query string:

                                            type BrowserVersionSupport struct {
                                              Chrome string
                                              Firefox string
                                            ver := BrowserVersionSupport{ Chrome: "37.0.2041.6", Firefox: "30.0" }

                                            If you have set Type to text or Content-Type to text/plain, content will be sent as raw string in body instead of form

                                              Send("hello world").

                                            func (*SuperAgent) SendFile

                                            func (s *SuperAgent) SendFile(file interface{}, args ...string) *SuperAgent

                                              SendFile function works only with type "multipart". The function accepts one mandatory and up to two optional arguments. The mandatory (first) argument is the file. The function accepts a path to a file as string:


                                              File can also be a []byte slice of a already file read by eg. ioutil.ReadFile:

                                              b, _ := ioutil.ReadFile("./example_file.ext")

                                              Furthermore file can also be a os.File:

                                              f, _ := os.Open("./example_file.ext")

                                              The first optional argument (second argument overall) is the filename, which will be automatically determined when file is a string (path) or a os.File. When file is a []byte slice, filename defaults to "filename". In all cases the automatically determined filename can be overwritten:

                                              b, _ := ioutil.ReadFile("./example_file.ext")
                                                SendFile(b, "my_custom_filename").

                                              The second optional argument (third argument overall) is the fieldname in the multipart/form-data request. It defaults to fileNUMBER (eg. file1), where number is ascending and starts counting at 1. So if you send multiple files, the fieldnames will be file1, file2, ... unless it is overwritten. If fieldname is set to "file" it will be automatically set to fileNUMBER, where number is the greatest exsiting number+1.

                                              b, _ := ioutil.ReadFile("./example_file.ext")
                                                SendFile(b, "", "my_custom_fieldname"). // filename left blank, will become "example_file.ext"

                                              func (*SuperAgent) SendMap

                                              func (s *SuperAgent) SendMap(content interface{}) *SuperAgent

                                              func (*SuperAgent) SendSlice

                                              func (s *SuperAgent) SendSlice(content []interface{}) *SuperAgent

                                                SendSlice (similar to SendString) returns SuperAgent's itself for any next chain and takes content []interface{} as a parameter. Its duty is to append slice of interface{} into s.SliceData ([]interface{}) which later changes into json array in the End() func.

                                                func (*SuperAgent) SendString

                                                func (s *SuperAgent) SendString(content string) *SuperAgent

                                                  SendString returns SuperAgent's itself for any next chain and takes content string as a parameter. Its duty is to transform String into s.Data (map[string]interface{}) which later changes into appropriate format such as json, form, text, etc. in the End func. Send implicitly uses SendString and you should use Send instead of this.

                                                  func (*SuperAgent) SendStruct

                                                  func (s *SuperAgent) SendStruct(content interface{}) *SuperAgent

                                                    SendStruct (similar to SendString) returns SuperAgent's itself for any next chain and takes content interface{} as a parameter. Its duty is to transfrom interface{} (implicitly always a struct) into s.Data (map[string]interface{}) which later changes into appropriate format such as json, form, text, etc. in the End() func.

                                                    func (*SuperAgent) Set

                                                    func (s *SuperAgent) Set(param string, value string) *SuperAgent

                                                      Set is used for setting header fields, this will overwrite the existed values of Header through AppendHeader(). Example. To set `Accept` as `application/json`

                                                        Set("Accept", "application/json").

                                                      func (*SuperAgent) SetBasicAuth

                                                      func (s *SuperAgent) SetBasicAuth(username string, password string) *SuperAgent

                                                        SetBasicAuth sets the basic authentication header Example. To set the header for username "myuser" and password "mypass"

                                                          SetBasicAuth("myuser", "mypass").

                                                        func (*SuperAgent) SetCurlCommand

                                                        func (s *SuperAgent) SetCurlCommand(enable bool) *SuperAgent

                                                          Enable the curlcommand mode which display a CURL command line

                                                          func (*SuperAgent) SetDebug

                                                          func (s *SuperAgent) SetDebug(enable bool) *SuperAgent

                                                            Enable the debug mode which logs request/response detail

                                                            func (*SuperAgent) SetDoNotClearSuperAgent

                                                            func (s *SuperAgent) SetDoNotClearSuperAgent(enable bool) *SuperAgent

                                                              Enable the DoNotClear mode for not clearing super agent and reuse for the next request

                                                              func (*SuperAgent) SetLogger

                                                              func (s *SuperAgent) SetLogger(logger Logger) *SuperAgent

                                                              func (*SuperAgent) TLSClientConfig

                                                              func (s *SuperAgent) TLSClientConfig(config *tls.Config) *SuperAgent

                                                                Set TLSClientConfig for underling Transport. One example is you can use it to disable security check (https):

                                                                gorequest.New().TLSClientConfig(&tls.Config{ InsecureSkipVerify: true}).

                                                                func (*SuperAgent) Timeout

                                                                func (s *SuperAgent) Timeout(timeout time.Duration) *SuperAgent

                                                                func (*SuperAgent) Type

                                                                func (s *SuperAgent) Type(typeStr string) *SuperAgent

                                                                  Type is a convenience function to specify the data type to send. For example, to send data as `application/x-www-form-urlencoded` :

                                                                    Send(`{ "name": "egg benedict", "category": "brunch" }`).

                                                                  This will POST the body "name=egg benedict&category=brunch" to url /recipe

                                                                  GoRequest supports

                                                                  "text/html" uses "html"
                                                                  "application/json" uses "json"
                                                                  "application/xml" uses "xml"
                                                                  "text/plain" uses "text"
                                                                  "application/x-www-form-urlencoded" uses "urlencoded", "form" or "form-data"