How to URL-encode in Go with net/url (query, path, full URL)
Table of Contents
URL encoding, also known as percent-encoding, makes URLs safe to transmit by encoding reserved characters. In Go, you handle this with the net/url package. ✅
In this guide, you will encode:
- query parameters
- path segments
- a full URL
- and learn how to decode when needed
What You’ll Learn #
- How to encode query parameters with
url.QueryEscapeandurl.Values - How to encode path segments with
url.PathEscape - How to build a full encoded URL safely
- How to decode values with
QueryUnescapeandPathUnescape
A quick URL anatomy #
scheme://host:port/path?query
Encode the query part of the URL #
The url.QueryEscape() function from the net/url package is used to encode a string placed inside a URL query.
package main
import (
"fmt"
"net/url"
)
func main() {
query1Val := url.QueryEscape("ab+c")
query2Val := url.QueryEscape("de$f")
fmt.Println(query1Val)
fmt.Println(query2Val)
}
Output:
ab%2Bc
de%24f
To create an encoded multiple key-value query parameters string, use the url.Values structure from the net/url package.
package main
import (
"fmt"
"net/url"
)
func main() {
queryValues := url.Values{}
queryValues.Add("query", "ab+c")
queryValues.Add("query2", "de$f")
encodedQuery := queryValues.Encode()
fmt.Println(encodedQuery)
}
Output:
query=ab%2Bc&query2=de%24f
Encode the path part of the URL #
The url.PathEscape() function from the net/url package is used to encode a string that is placed inside a URL path segment. The path segment is encoded differently from the query, for example, the + character is allowed in the path, and should be encoded in the query.
package main
import (
"fmt"
"net/url"
)
func main() {
path := url.PathEscape("foo+bar!")
fmt.Println(path)
}
Output:
foo+bar%21
Build a full encoded URL #
There are two ways to construct a full encoded URL. You can create it manually by joining different parts of the URL, where the query and path parts are escaped with the previously used functions.
package main
import (
"fmt"
"net/url"
)
func main() {
// build url manually
host := "https://example.com/"
path := url.PathEscape("foo+bar!")
query1Val := url.QueryEscape("ab+c")
query2Val := url.QueryEscape("de$f")
query := fmt.Sprintf("query=%s&query2=%s", query1Val, query2Val)
fmt.Printf("%s %s%s?%s\n", "Manually built URL:", host, path, query)
}
Output:
Manually built URL: https://example.com/foo+bar%21?query=ab%2Bc&query2=de%24f
However, it is generally better idea to build the encoded URL by using the url.URL structure. This way is easier and less error-prone than manually constructing the resulting URL. You just need to set the Scheme, Host, Path of the URL and build the RawQuery string by encoding query parameters inside the url.Values struct.
package main
import (
"fmt"
"net/url"
)
func main() {
// build url using url.URL struct
exampleURL := &url.URL{
Scheme: "https",
Host: "example.com",
Path: "/foo+bar!",
}
queryValues := url.Values{}
queryValues.Add("query", "ab+c")
queryValues.Add("query2", "de$f")
exampleURL.RawQuery = queryValues.Encode()
fmt.Printf("%s %s\n", "URL built using url.URL struct:", exampleURL)
}
URL built using url.URL struct: https://example.com/foo+bar%21?query=ab%2Bc&query2=de%24f
Decode URL-encoded values (related utilities) #
Use these when you need to read encoded values back:
url.QueryUnescape()for query parametersurl.PathUnescape()for path segments
package main
import (
"fmt"
"net/url"
)
func main() {
decodedQuery, _ := url.QueryUnescape("ab%2Bc")
decodedPath, _ := url.PathUnescape("foo+bar%21")
fmt.Println(decodedQuery)
fmt.Println(decodedPath)
}
Output:
ab+c
foo+bar!
Common mistakes #
❌ Using QueryEscape for a path segment:
path := url.QueryEscape("foo+bar!") // "+" becomes "%2B" (not what you want)
✅ Use PathEscape for path segments:
path := url.PathEscape("foo+bar!")
❌ Manually concatenating query strings without encoding:
query := "q=go+tips&tag=c#"
✅ Use url.Values:
values := url.Values{}
values.Add("q", "go+tips")
values.Add("tag", "c#")
query := values.Encode()
Best practices #
- Use
url.Valuesfor query strings to avoid subtle encoding bugs. - Use
url.URLto assemble full URLs safely. - Encode only the parts you control, not the entire URL string.
Related topics #
- URL decode in Go - reverse percent-encoding
- Join URL elements in Go - safe path assembly
- HTTP client timeout in Go - robust requests
- Print HTTP request and response in Go - inspect URLs and headers
- REST client in Go - complete request examples
Tested with Go 1.25+ | Last verified: December 2025 🎉