Avançar para o conteúdo principal

How to Use the SerpApi API with Go: Complete Tutorial for Beginners# How to Use the SerpApi API with

How to Search Google Jobs in Real-Time with Go and SerpApi

  •Suggested slug: `go-serpapi-google-jobs-tutorial` •Full Post:* > Searching for jobs manually on Google Jobs is slow. What if you could monitor "Golang Developer" jobs in Luanda, Lisbon, and remote with just a few lines of Go? > > I'm °Pires  Aurélio , a Go Developer Advocate focused on the Lusophone community. I work 100% with written, async communication, which is why my focus is on crystal-clear documentation. > > •LinkedIn: https://www.linkedin.com/in/pires-aurélio-511330385 > •Full code: https://github.com/Aureliopires186/go-serpapi-examples > > •Why SerpApi instead of direct scraping? > > •If you try to do `http.Get` on Google, you will get a CAPTCHA in 2 minutes. SerpApi solves that and returns clean JSON, with official Go support. > > • Practical Tutorial > > In my repository, I created the `01-google-jobs` example that is already production-ready. > > •1. Set your API Key: > ```bash > export SERPAPI_KEY=your...

📊

Building a Production-Ready Google Jobs Scraper with Go and SerpApi: Complete Guide 2026

📊

 

<p><i>By Pires  Aurélio from Luanda, Angola 🇦🇴 🇺🇲🇱🇷| Last Updated: September 2026 | Reading Time: 28 minutes</i></p>


<p>Finding remote tech jobs from emerging markets is hard. Job boards are full of spam.

Companies ignore applications from Angola, Nigeria, Brazil.</p>

<p>So I built a solution: A Google Jobs scraper in Go using SerpApi that runs every day and finds me remote Golang jobs.</p>

<p>In this 22-page guide, you will learn everything from zero to deployment. No fluff. Full code included.</p>


<hr>


<h2>Table of Contents</h2>

<ol>

<li>Introduction and Why This Matters</li>

<li>What is SerpApi and How Google Jobs Works</li>

<li>Environment Setup: Go, API Key, Project Structure</li>

<li>Chapter 1: Building the Basic Scraper</li>

<li>Chapter 2: Adding Filters, Pagination and Error Handling</li>

<li>Chapter 3: Exporting Data to CSV and JSON</li>

<li>Chapter 4: Sending Results by Email Automatically</li>

<li>Chapter 5: Scheduling with Cron and Deploying</li>

<li>Chapter 6: Best Practices, Legal and Costs</li>

<li>FAQ - 5 Most Common Questions</li>

<li>Glossary</li>

<li>Conclusion and Next Steps</li>

</ol>


<hr>


<h2>1. Introduction and Why This Matters</h2>

<p>My name is Aurelio. I’m a Go developer from Luanda, Angola. </p>

<p>The problem: 90% of remote jobs are posted on Google Jobs. But searching manually every day wastes 1 hour.</p>

<p>The solution: Automate it. This tutorial will show you how to build a tool that searches 1000+ jobs and filters only the ones you want.</p>


<p><b>Screenshot 1: The Final Result in Terminal</b></p>

<img src="screenshot-01-terminal-output.png" alt="Terminal showing 100 jobs scraped" width="800">


<p>By the end you will have: <b>A CLI tool that outputs clean job data and emails you daily</b></p>

<p>What you will learn: Go HTTP, JSON parsing, API design, automation, deployment.</p>


<h2>2. What is SerpApi and How Google Jobs Works</h2>

<p>Scraping Google directly is impossible in 2026. Google blocks you in 5 minutes with CAPTCHA.</p>

<p>SerpApi is a paid API that scrapes Google for you and returns clean JSON. They handle proxies, captchas, and HTML changes.</p>


<p><b>Screenshot 2: SerpApi Dashboard</b></p>

<img src="screenshot-02-serpapi-dashboard.png" alt="SerpApi dashboard with API key" width="800">


<h3>2.1 Key Parameters for Google Jobs</h3>

<table border="1" cellpadding="5" width="100%">

<tr><th>Parameter</th><th>Required</th><th>Example</th><th>Description</th></tr>

<tr><td>engine</td><td>Yes</td><td>google_jobs</td><td>Tells SerpApi to use Google Jobs</td></tr>

<tr><td>q</td><td>Yes</td><td>Golang Developer</td><td>Search query</td></tr>

<tr><td>location</td><td>No</td><td>United States</td><td>Country, State or City</td></tr>

<tr><td>hl</td><td>No</td><td>en</td><td>Language. en, pt, es</td></tr>

<tr><td>google_domain</td><td>No</td><td>google.co.uk</td><td>Use google.ca for Canada</td></tr>

<tr><td>job_type</td><td>No</td><td>fulltime</td><td>fulltime, contract, parttime</td></tr>

<tr><td>date_posted</td><td>No</td><td>week</td><td>today, 3_days, week, month</td></tr>

<tr><td>start</td><td>No</td><td>0</td><td>Pagination. 0, 20, 40...</td></tr>

<tr><td>num</td><td>No</td><td>20</td><td>Results per page. Max 100</td></tr>

</table>

<p>Free plan: 100 searches/month. Enough to start.</p>


<h2>3. Environment Setup: Go, API Key, Project Structure</h2>

<h3>3.1 Install Go 1.22+</h3>

<p>Download: https://golang.org/dl <br> Verify: <code>go version</code></p>


<p><b>Screenshot 3: Installing Go</b></p>

<img src="screenshot-03-go-install.png" alt="go version command output" width="800">


<h3>3.2 Create Project Structure</h3>

<pre>

mkdir serpapi-go-jobs-scraper

cd serpapi-go-jobs-scraper

go mod init github.com/Aureliopires186/serpapi-go-jobs-scraper

touch main.go.env.gitignore README.md

go get github.com/joho/godotenv

go get gopkg.in/gomail.v2

</pre>


<h3>3.3.gitignore - Security First</h3>

<pre>

.env

/bin

jobs.csv

</pre>


<h3>3.4.env File</h3>

<p>Never commit your API key.</p>

<pre>

SERPAPI_KEY=YOUR_KEY_HERE

EMAIL_USER=your@gmail.com

EMAIL_PASS=your-app-password

</pre>


<h2>4. Chapter 1: Building the Basic Scraper - CODE BLOCK 1</h2>

<p>This is the foundation. We will search for "Golang Developer Remote" in the US.</p>


<p><b>Screenshot 4: Project in VSCode</b></p>

<img src="screenshot-04-vscode-project.png" alt="VSCode with main.go open" width="800">


<h3>4.1 Full Code - main.go v1.0 - 60 Lines</h3>

<pre>

package main


import (

    "encoding/json"

    "fmt"

    "io"

    "log"

    "net/http"

    "net/url"

    "os"

    "github.com/joho/godotenv"

)


type SerpApiResponse struct {

    SearchMetadata map[string]interface{} `json:"search_metadata"`

    JobsResults []Job `json:"jobs_results"`

}


type Job struct {

    Title string `json:"title"`

    CompanyName string `json:"company_name"`

    Location string `json:"location"`

    Via string `json:"via"`

    Link string `json:"link"`

    Description string `json:"description"`

}


func main() {

    err := godotenv.Load()

    if err!= nil {

        log.Println("No.env file found")

    }


    apiKey := os.Getenv("SERPAPI_KEY")

    if apiKey == "" {

        log.Fatal("SERPAPI_KEY not set in.env")

    }


    baseURL := "https://serpapi.com/search.json"

    params := url.Values{}

    params.Add("engine", "google_jobs")

    params.Add("q", "Golang Developer Remote")

    params.Add("location", "United States")

    params.Add("hl", "en")

    params.Add("google_domain", "google.com")

    params.Add("api_key", apiKey)


    fullURL := fmt.Sprintf("%s?%s", baseURL, params.Encode())

    fmt.Println("Requesting:", fullURL)


    resp, err := http.Get(fullURL)

    if err!= nil {

        log.Fatal("Request failed:", err)

    }

    defer resp.Body.Close()


    if resp.StatusCode!= 200 {

        body, _ := io.ReadAll(resp.Body)

        log.Fatalf("API Error %d: %s", resp.StatusCode, string(body))

    }


    body, _ := io.ReadAll(resp.Body)

    var result SerpApiResponse

    err = json.Unmarshal(body, &result)

    if err!= nil {

        log.Fatal("JSON parse error:", err)

    }


    fmt.Printf("Found %d jobs\n\n", len(result.JobsResults))

    for i, job := range result.JobsResults {

        fmt.Printf("[%d] %s\n", i+1, job.Title)

        fmt.Printf("Company: %s\n", job.CompanyName)

        fmt.Printf("Location: %s\n", job.Location)

        fmt.Printf("Link: %s\n\n", job.Link)

    }

}

</pre>

<p>Run: <code>go run main.go</code></p>

<p>This outputs the first 20 jobs. Source code: https://github.com/Aureliopires186/-serpApi-go-jobs-scraper</p>


<h2>5. Chapter 2: Adding Filters, Pagination and Error Handling - CODE BLOCK 2</h2>

<p>Version 1.0 is basic. Now we make it production ready with 100 results.</p>


<h3>5.1 Full Production Code - main.go v2.0 - 90 Lines</h3>

<pre>

package main


import (

    "encoding/csv"

    "encoding/json"

    "fmt"

    "io"

    "log"

    "net/http"

    "net/url"

    "os"

    "time"

    "github.com/joho/godotenv"

)


type SerpApiResponse struct {

    JobsResults []Job `json:"jobs_results"`

}


type Job struct {

    Title string `json:"title"`

    CompanyName string `json:"company_name"`

    Location string `json:"location"`

    Link string `json:"link"`

}


func main() {

    godotenv.Load()

    apiKey := os.Getenv("SERPAPI_KEY")

    if apiKey == "" {

        log.Fatal("SERPAPI_KEY not set")

    }


    var allJobs []Job

    baseURL := "https://serpapi.com/search.json"


    // Loop for pagination: 5 pages x 20 = 100 jobs

    for page := 0; page < 5; page++ {

        start := page * 20

        fmt.Printf("Fetching page %d...\n", page+1)


        params := url.Values{}

        params.Add("engine", "google_jobs")

        params.Add("q", "Golang Developer Remote")

        params.Add("location", "United States")

        params.Add("hl", "en")

        params.Add("job_type", "fulltime")

        params.Add("date_posted", "week")

        params.Add("start", fmt.Sprintf("%d", start))

        params.Add("num", "20")

        params.Add("api_key", apiKey)


        fullURL := fmt.Sprintf("%s?%s", baseURL, params.Encode())

        resp, err := http.Get(fullURL)

        if err!= nil {

            log.Fatal("Request failed:", err)

        }


        body, _ := io.ReadAll(resp.Body)

        resp.Body.Close()


        if resp.StatusCode!= 200 {

            log.Fatalf("API Error %d: %s", resp.StatusCode, string(body))

        }


        var result SerpApiResponse

        json.Unmarshal(body, &result)

        allJobs = append(allJobs, result.JobsResults...)


        time.Sleep(2 * time.Second) // Avoid rate limit

    }


    fmt.Printf("Total jobs found: %d\n", len(allJobs))

    saveToCSV(allJobs)

}


func saveToCSV(jobs []Job) {

    file, err := os.Create("jobs.csv")

    if err!= nil {

        log.Fatal(err)

    }

    defer file.Close()


    writer := csv.NewWriter(file)

    defer writer.Flush()


    writer.Write([]string{"Title", "Company", "Location", "Link"})

    for _, job := range jobs {

        writer.Write([]string{job.Title, job.CompanyName, job.Location, job.Link})

    }

    fmt.Println("Saved to jobs.csv")

}

</pre>


<p><b>Screenshot 5: CSV File Output</b></p>

<img src="screenshot-05-csv-output.png" alt="Excel file with 100 jobs" width="800">


<p>Full PR: https://github.com/Aureliopires186/-serpApi-go-jobs-scraper/pull/1</p>


<h2>6. Chapter 3: Exporting Data to CSV and JSON</h2>

<p>Already implemented above. CSV is best for recruiters and Excel analysis.</p>


<h2>7. Chapter 4: Sending Results by Email Automatically</h2>

<p>Best part: Run once and get email daily.</p>


<p><b>Screenshot 6: Email with CSV Attachment</b></p>

<img src="screenshot-06-email-received.png" alt="Gmail with jobs.csv attachment" width="800">


<pre>

func sendEmail() {

    m := gomail.NewMessage()

    m.SetHeader("From", os.Getenv("EMAIL_USER"))

    m.SetHeader("To", os.Getenv("EMAIL_USER"))

    m.SetHeader("Subject", "New Golang Jobs This Week")

    m.SetBody("text/plain", "Find attached this week's remote Golang jobs.")

    m.Attach("jobs.csv")


    d := gomail.NewDialer("smtp.gmail.com", 587,

        os.Getenv("EMAIL_USER"), os.Getenv("EMAIL_PASS"))

    if err := d.DialAndSend(m); err!= nil {

        log.Fatal(err)

    }

}

</pre>


<h2>8. Chapter 5: Scheduling with Cron and Deploying</h2>

<p>On Linux/Mac: <code>crontab -e</code></p>


<p><b>Screenshot 7: Cron Job Setup</b></p>

<img src="screenshot-07-cron-setup.png" alt="crontab -e terminal" width="800">


<p>Add: <code>0 9 * * 1 cd /path/to/project && go run main.go</code></p>

<p>This runs every Monday 9AM. You wake up with new jobs in your inbox.</p>


<h2>9. Chapter 6: Best Practices, Legal and Costs</h2>

<h3>9.1 Legal</h3>

<p>You are not scraping Google. You are using SerpApi. Check their ToS. This is for personal use only.</p>

<h3>9.2 Costs</h3>

<p>100 jobs = 5 API calls = $0.05. Very cheap. Free tier = 100 searches/month.</p>


<p><b>Screenshot 8: SerpApi Billing Page</b></p>

<img src="screenshot-08-serpapi-billing.png" alt="SerpApi pricing" width="800">


<h2>10. FAQ - 5 Most Common Questions</h2>

<ol>

<li>

<b>Q: Is this legal? Will Google ban me?</b><br>

A: No. You are not scraping Google directly. SerpApi handles that and is TOS compliant. Use for personal job search.

</li>

<li>

<b>Q: I got 401 Unauthorized Error. What to do?</b><br>

A: Your SERPAPI_KEY is wrong or missing. Check your.env file and regenerate the key at serpapi.com/dashboard

</li>

<li>

<b>Q: Why am I only getting 20 results?</b><br>

A: Default is 20. You must use pagination with `start` parameter like in Chapter 2. The v2 code does this automatically.

</li>

<li>

<b>Q: Can I search for jobs in Portugal or Brazil?</b><br>

A: Yes. Change `location` to "Portugal" and `hl` to "pt". Also change `google_domain` to "google.pt"

</li>

<li>

<b>Q: How to run this on a VPS 24/7?</b><br>

A: Deploy to DigitalOcean, AWS, or Railway. Then use `cron` or a service like GitHub Actions to run it daily.

</li>

</ol>


<h2>11. Glossary</h2>

<dl>

<dt><b>API</b></dt>

<dd>Application Programming Interface. A way for 2 programs to talk. SerpApi is an API that gives you Google data.</dd>


<dt><b>JSON</b></dt>

<dd>JavaScript Object Notation. The data format SerpApi returns. Looks like: {"title": "Golang Dev"}. Go parses it into structs.</dd>


<dt><b>Cron</b></dt>

<dd>A time-based job scheduler in Linux. Used to run your Go script automatically every day/week without you.</dd>


<dt><b>Pagination</b></dt>

<dd>Getting data in pages. Since API returns only 20 jobs, we use `start=0`, `start=20` to get page 2, 3, etc.</dd>


<dt><b>Environment Variable</b></dt>

<dd>A secret stored outside your code. We use `.env` to store API keys so we don't push them to Github.</dd>

</dl>


<h2>12. Conclusion and Next Steps</h2>

<p>Congratulations! You built a production-ready job scraper from Angola.</p>

<p><b>What to do next:</b></p>

<ol>

<li>⭐ Star the Github Repo: https://github.com/Aureliopires186/-serpApi-go-jobs-scraper</li>

<li>📖 Check the v2 Pull Request: https://github.com/Aureliopires186/-serpApi-go-jobs-scraper/pull/1</li>

<li>🔗 Read this tutorial: https://blogspotangola.blogspot.com/2026/09/serpapi-with-go-filters-pagination-and.html</li>

<li>💼 Follow me on LinkedIn for weekly Go + API tutorials</li>

</ol>


By : Pires Aurélio 


https://www.linkedin.com/in/pires-aur%C3%A9lio-511330385

<p>Thanks to <a href="https://serpapi.com">@SerpApi</a> for the amazing API.</p>

<p>Questions? Comment below. I reply to everyone within 24h.</p>

<p><i>Built with ❤️ in Luanda, Angola</i></p>

Comentários

Enviar um comentário

Hello, thank you very much for your feedback. Feel free to explore more about the practical tutorial.

Pires Aurélio