Golang set cookie and golang http cookie with net/http

Golang set cookie with http.SetCookie and http.Cookie, golang http cookie headers, golang cookies and cookie golang reads via Request.Cookie, Path Domain MaxAge Expires SameSite Secure HttpOnly, order before Write, curl examples, delete cookie, and silent invalid cookie drop.

Published

Updated

Read time 4 min read

Reviewed byDeepak Prasad

Golang set cookie and golang http cookie with net/http

People search golang set cookie, golang set-cookie, golang cookie, golang cookies, golang http cookie, cookie golang, go cookie, and golang http set cookie for the same task: send a Set-Cookie response header from a Go server (usually net/http). The standard entry point is http.SetCookie with an http.Cookie value. This guide shows server-side golang cookies, how to read them back on the next request, ordering pitfalls (competitors and Stack Overflow stress this), security fields, deletion, and curl traces you can reproduce without a browser recording. For the wider HTTP surface, see HTTP in Go; for struct syntax used by http.Cookie, see structs in Go.

Examples assume a recent Go toolchain on Linux. curl samples were captured against a local 127.0.0.1:18080 demo; use another port if yours is busy.


http.SetCookie(w, cookie) adds a Set-Cookie header to the response header map for ResponseWriter w. The browser (or HTTP client) stores the cookie and sends a Cookie header on later requests that match Path, Domain, SameSite, etc.

Call SetCookie before any handler code that writes the response body and triggers a flush. After the first Write that sends headers, extra Set-Cookie calls may have no effect—the behavior that surprises newcomers and is documented around ResponseWriter.

Fields you usually set

Field Role
Name, Value Required logical pair; Name must be a valid token (see http.Cookie.String validation).
Path, Domain Scope which URLs receive the cookie; wrong Path is a common "cookie not sent" bug.
MaxAge Seconds until expiry; MaxAge < 0 asks the browser to delete the cookie; 0 means do not send Max-Age (pair with Expires if you set it).
Expires Absolute expiry time (HTTP-date); many APIs prefer MaxAge for sliding sessions.
HttpOnly Hides the cookie from document.cookie in browsers—use on session IDs.
Secure Send only on HTTPS connections.
SameSite http.SameSiteStrictMode, Lax, or None (None generally needs Secure).

http.SetCookie does not return error; if the cookie fails validation, it may be silently omitted—check Cookie.String length in development (very long Set-Cookie lines are rejected).


Minimal server: set then read golang cookies

This program exposes /set (sets sid) and /read (prints one cookie). Save as main.go, run go run ., then use the curl commands in the next section.

go
package main

import (
	"fmt"
	"net/http"
)

func setHandler(w http.ResponseWriter, r *http.Request) {
	c := &http.Cookie{
		Name:     "sid",
		Value:    "abc123",
		Path:     "/",
		MaxAge:   3600,
		HttpOnly: true,
		Secure:   false,
		SameSite: http.SameSiteLaxMode,
	}
	http.SetCookie(w, c)
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	fmt.Fprint(w, "ok\n")
}

func readHandler(w http.ResponseWriter, r *http.Request) {
	if c, err := r.Cookie("sid"); err == nil {
		fmt.Fprintf(w, "sid=%s\n", c.Value)
	} else {
		fmt.Fprintf(w, "no sid: %v\n", err)
	}
}

func main() {
	http.HandleFunc("/set", setHandler)
	http.HandleFunc("/read", readHandler)
	http.ListenAndServe("127.0.0.1:18080", nil)
}

Issue a HEAD request to /set and inspect headers (line breaks normalized):

text
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Set-Cookie: sid=abc123; Path=/; Max-Age=3600; HttpOnly; SameSite=Lax
Date: Thu, 18 Jun 2026 02:39:39 GMT
Content-Length: 3

GET /read without a Cookie header shows the server side when the browser never stored or sent sid:

text
no sid: http: named cookie not present

Send a browser-style Cookie header:

bash
curl -s -b 'sid=fromcurl' http://127.0.0.1:18080/read
text
sid=fromcurl

To list every cookie name/value pair on a request, loop r.Cookies() instead of r.Cookie("name").


Deletion is done by re-issuing a cookie with the same Name, Path, and Domain, and either MaxAge: -1 or an Expires in the past (RFC 6265 cookie eviction rules in browsers).

You may call http.SetCookie multiple times per response; each call appends another Set-Cookie header for different names or attribute variants.


Servers set cookies; http.Client with a non-nil Jar stores Set-Cookie from responses and sends Cookie on matching follow-up requests. The standard library includes net/http/cookiejar for many CLI tools and tests.


  • Prefer HttpOnly on authentication cookies to reduce theft via injected scripts.
  • Use Secure in production behind HTTPS.
  • Choose SameSite: Lax is a common default for session cookies on sites that do not need cross-site POST embedding; Strict is tighter; SameSiteNoneMode requires Secure for modern browsers.
  • Never copy example secrets into production; rotate tokens and treat cookies as opaque handles, not trusted storage.
  • For CSRF, cookies alone are not enough; pair with CSRF tokens or framework middleware where appropriate.

Summary

Golang set cookie flows use http.SetCookie with a populated http.Cookie: that is how you emit golang set-cookie headers for go cookie and golang cookies scenarios alike. Golang http cookie input on the server comes from Request.Cookie or Request.Cookies. The highest-impact detail for reliability is header order: set golang http cookie headers before the body. Layer SameSite, Secure, and HttpOnly for real traffic, remember SetCookie can silently drop bad cookies, and verify behavior with curl -v or browser devtools when debugging.


References


Frequently Asked Questions

1. How do I golang set cookie on a response?

Build an http.Cookie pointer and call http.SetCookie(w, &cookie) on the ResponseWriter before the first Write that flushes headers; it emits a Set-Cookie header.

2. Why is my golang http cookie missing in the browser?

Headers are fixed after the first body write; calling SetCookie after fmt.Fprintf or io.WriteString can be ignored. Set cookies first, then write the body.

3. How do I read golang cookies from an incoming request?

Use r.Cookie("name") for one cookie or r.Cookies() for all; on a client, use Jar on http.Client or read Set-Cookie from the response.

4. Does http.SetCookie return an error if the cookie is invalid?

No; invalid cookies may be dropped silently, so validate Name, length, and attributes in your own code before calling SetCookie.

5. What is the difference between MaxAge and Expires on http.Cookie?

MaxAge is seconds from now (MaxAge 0 omits Max-Age; negative deletes); Expires sets an absolute time—prefer MaxAge for relative sessions when both are optional.

6. When should I set SameSite, Secure, and HttpOnly?

Use HttpOnly on session tokens to reduce XSS theft, Secure on HTTPS sites, and SameSite (often Lax) to reduce CSRF on cross-site navigations.
Tuan Nguyen

Data Scientist

Proficient in Golang, Python, Java, MongoDB, Selenium, Spring Boot, Kubernetes, Scrapy, API development, Docker, Data Scraping, PrimeFaces, Linux, Data Structures, and Data Mining. With expertise …