← Back to blog

Google Search API in Go: Complete Tutorial (2026)

Call a Google Search API from Go (Golang) — runnable net/http example, JSON structs, curl test. 100 free searches, pay-as-you-go from $0.75/1k.

1 min read

Query Google from Go with just the standard library, using serp.cheap — or drop in the official Go SDK (go get github.com/serpcheap/serpcheap-go). It’s a plain HTTP+JSON endpoint either way.

Quick sanity check with curl first:

curl -X POST https://api.serp.cheap/v1/search \
  -H "X-API-Key: $SERP_CHEAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"q":"best electric cars 2026","gl":"us"}'

The same call in Go — one complete file, runnable as-is with go run main.go (set SERP_CHEAP_API_KEY first):

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
)

type Result struct {
	Position int    `json:"position"`
	Title    string `json:"title"`
	Link     string `json:"link"`
	Snippet  string `json:"snippet"`
}

type Response struct {
	Organic []Result `json:"organic"`
	Stats   struct {
		Balance int  `json:"balance"`
		Cost    int  `json:"cost"`
		Cached  bool `json:"cached"`
	} `json:"stats"`
}

func search(apiKey, q, gl string, page int) (*Response, error) {
	body, err := json.Marshal(map[string]any{"q": q, "gl": gl, "page": page})
	if err != nil {
		return nil, err
	}
	req, err := http.NewRequest("POST", "https://api.serp.cheap/v1/search", bytes.NewReader(body))
	if err != nil {
		return nil, err
	}
	req.Header.Set("X-API-Key", apiKey)
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("search failed: HTTP %d", resp.StatusCode)
	}
	var out Response
	if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
		return nil, err
	}
	return &out, nil
}

func main() {
	apiKey := os.Getenv("SERP_CHEAP_API_KEY")
	if apiKey == "" {
		fmt.Fprintln(os.Stderr, "SERP_CHEAP_API_KEY is not set")
		os.Exit(1)
	}
	res, err := search(apiKey, "best electric cars 2026", "us", 1)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	for _, r := range res.Organic {
		fmt.Printf("#%d %s — %s\n", r.Position, r.Title, r.Link)
	}
	fmt.Printf("cost: %d credits, cached: %v\n", res.Stats.Cost, res.Stats.Cached)
}

Example output:

#1 Best Electric Cars of 2026: Tested and Ranked — https://www.example.com/best-electric-cars-2026
#2 The 10 Best EVs You Can Buy Right Now — https://www.example.org/ev-buying-guide
#3 Electric Car Reviews & Comparisons — https://www.example.net/electric-cars
cost: 6 credits, cached: false

page is 1-indexed; pass 2 for the second results page. gl sets the country (12 supported: US, BR, GB, DE, FR, ES, IT, MX, CA, AU, JP, NL), and you can add hl for the interface language or tbs for time filters to the JSON body.

For production, add a retry on 429/5xx with exponential backoff and a context.Context timeout.

Next

Try serp.cheap

Drop the file above into main.go and you’re pulling Google results from Go in under a minute. 100 free searches on signup — no card required; pay-as-you-go from $0.75/1k after that, and credits stay valid for 12 months.

Frequently asked questions

How do I call a Google Search API in Go?+

Use net/http to POST a JSON body to the SERP API and decode the response into a struct. With serp.cheap the endpoint is https://api.serp.cheap/v1/search with an X-API-Key header.

Do I need a third-party Go SDK?+

No — the standard library's net/http and encoding/json are enough. A SERP API is a plain HTTP+JSON endpoint.

Get your API key

Cheapest direct, pay by card or crypto, no KYC. Or use a marketplace.