PromptHub
Developer Tools Go Programming

Stop Wrestling with Google Places API! Use goplaces Instead

B

Bright Coding

Author

14 min read
27 views
Stop Wrestling with Google Places API! Use goplaces Instead

Stop Wrestling with Google Places API! Use goplaces Instead

Have you ever stared at a Google Places API response, wondering why you needed to hand-craft field masks, wrestle with nested JSON payloads, and write yet another wrapper function just to find coffee shops near your office? You're not alone. Every developer who touches the Google Places API (New) eventually hits the same wall: the documentation is comprehensive, but the developer experience is exhausting. You need a PhD in Google's API taxonomy just to get a place's phone number and opening hours.

What if you could fire off a single terminal command and get beautifully formatted place data? What if the same tool also spat out stable JSON for your automation pipelines? What if you never had to write another field mask again?

Enter goplaces — the modern Go client and CLI for the Google Places API that top developers are quietly adopting to 10x their location data workflows. Built by Peter Steinberger (yes, that Peter Steinberger, the PSPDFKit founder and iOS legend who knows a thing or two about polished developer tools), goplaces transforms one of Google's most powerful but frustrating APIs into something you actually enjoy using.

Stop fighting the API. Start shipping. Here's everything you need to know.

What is goplaces?

goplaces is a modern Go client and command-line interface for the Google Places API (New), with bonus support for selected Routes API workflows. It's the tool you reach for when you need Google place data from a terminal, shell script, AI agent, or Go program — without the soul-crushing boilerplate of hand-written field masks and request payloads.

The project lives at github.com/steipete/goplaces and represents a refreshing take on API tooling. Where most Google API clients feel like they were generated by robots for robots, goplaces keeps the human CLI pleasant while ensuring the same commands emit stable JSON for automation. It's the rare tool that succeeds equally well for interactive exploration and production scripting.

Peter Steinberger released v0.4.0 on May 4, 2026, and the project is gaining serious traction among Go developers who've tasted the alternative: wrestling with Google's official client libraries or, worse, building their own abstractions from scratch. The documentation site at goplaces.sh rounds out the experience with polished guides.

Why is it trending now? Three forces are converging:

  1. The Places API (New) finally offers modern features developers actually want, but Google's official tooling lags behind.
  2. AI agents and automation need reliable, structured location data — and JSON output is non-negotiable.
  3. Go's CLI ecosystem has matured, and developers expect tools that feel native to their workflow, not foreign objects bolted onto legacy APIs.

goplaces delivers on all three. It's not just a wrapper — it's a reimagining of how developers should interact with location services.

Key Features That Make goplaces Irresistible

Let's dissect what makes this tool special under the hood.

Dual-Personality Output Engine By default, goplaces renders compact, colorized text perfect for human scanning. Need to pipe results into jq or feed an AI agent? Add --json and get predictable, structured output. No parsing hacks, no regex extraction, no tears.

Complete Places API (New) Coverage The library wraps every major endpoint: Text Search, Nearby Search, Place Details, Autocomplete, Photo Media, and Resolve. Each command maps to intuitive CLI verbs — search, nearby, details, autocomplete, photo, resolve — so you spend zero time memorizing Google's endpoint naming conventions.

Routes API Integration This is where goplaces pulls ahead of generic API clients. It combines Routes API polyline sampling with Places search, enabling genuinely useful workflows like "find coffee shops along my drive from Seattle to Portland." Plus full directions support with travel modes, route modifiers, and unit preferences.

Smart Field Mask Management Here's the secret sauce: field masks are defined alongside each request type in the Go source (search.go, details.go, autocomplete.go, etc.). You never touch them. The library requests exactly what it needs, keeping responses lean and your code clean.

Flexible Authentication Environment variables for automation, CLI flags for ad-hoc exploration, and optional base URL overrides for testing with proxies or mock servers. The GOOGLE_PLACES_API_KEY is your primary key, with GOOGLE_PLACES_BASE_URL, GOOGLE_ROUTES_BASE_URL, and GOOGLE_DIRECTIONS_BASE_URL available when you need them.

Production-Ready Go Library The root package github.com/steipete/goplaces offers a stable public API. Build your own tools, embed location intelligence in services, or extend the CLI. The architecture separates concerns cleanly: cmd/goplaces for the CLI entrypoint, internal/places for API implementation, and internal/cli for parsing and rendering.

Real-World Use Cases Where goplaces Dominates

1. Rapid Location Research for Product Teams

Your PM needs competitive analysis on coffee shops in Manhattan right now. Instead of opening Google Maps like a civilian, you run:

goplaces search "specialty coffee" --min-rating 4.2 --open-now --limit 20 \
  --lat 40.7282 --lng -73.9942 --radius-m 2000 --json | jq '.[] | {name, rating, address}'

Structured data, instant export, no manual transcription. You've just saved an hour of copy-paste hell.

2. AI Agent Location Intelligence

Building a travel planning agent? goplaces gives your LLM reliable tool calls. The JSON output schema is stable and predictable — critical for prompt engineering. Your agent can search, get details, check hours, and route between destinations without you maintaining fragile API integration code.

3. Shell Script Automation

Need nightly reports on business status changes for your franchise locations? Script it:

#!/bin/bash
for place_id in $(cat locations.txt); do
  goplaces details "$place_id" --json | jq '{id: .place_id, status: .business_status, open: .open_now}'
done

No OAuth dance, no token refresh logic, no SDK dependencies beyond a single binary.

4. Route-Aware Discovery Apps

The killer feature most developers miss: goplaces route samples your driving polyline and searches near waypoints. Building a road trip planner? Gas station finder for logistics? This single command replaces hundreds of lines of custom geospatial code:

goplaces route "electric vehicle charging" --from "San Francisco, CA" --to "Los Angeles, CA" --max-waypoints 8

5. Development and Testing Workflows

The base URL overrides and E2E test configuration make goplaces perfect for mock server testing. Point at your staging environment, control query parameters via environment variables, and validate your integration without burning production quota.

Step-by-Step Installation & Setup Guide

Ready to escape API purgatory? Here's your escape route.

Installation (Choose Your Path)

Homebrew (Recommended for macOS/Linux):

brew install steipete/tap/goplaces

Go Install (Any platform with Go 1.21+):

go install github.com/steipete/goplaces/cmd/goplaces@latest

From Source:

git clone https://github.com/steipete/goplaces.git
cd goplaces
make goplaces

Verify your installation:

goplaces --help

Google Cloud API Setup

This is the one-time pain that unlocks perpetual convenience. Follow precisely:

Step 1: Create a Google Cloud Project

  • Visit Google Cloud Console
  • Click "Select a project" → "New Project"
  • Name it (e.g., "goplaces-production") and click "Create"

Step 2: Enable Required APIs

  • Navigate to APIs & Services → Library
  • Search and enable "Places API (New)" — critically, the one with (New) in the name
  • Search and enable "Routes API" (needed for route and directions commands)

Step 3: Generate API Key

Step 4: Configure Environment

export GOOGLE_PLACES_API_KEY="your-actual-key-here"

Persist it by adding to ~/.zshrc or ~/.bashrc:

echo 'export GOOGLE_PLACES_API_KEY="your-actual-key-here"' >> ~/.zshrc
source ~/.zshrc

Step 5: Secure Your Key (Critical!)

  • In Credentials, click your key
  • Under "API restrictions", select "Restrict key"
  • Add only "Places API (New)" and "Routes API"
  • Set quota limits in Quotas — the Places API has real costs!

Optional Configuration

For testing with proxies or mock servers:

export GOOGLE_PLACES_BASE_URL="https://your-mock-server.test"
export GOOGLE_ROUTES_BASE_URL="https://your-mock-server.test/routes"
export GOOGLE_DIRECTIONS_BASE_URL="https://your-mock-server.test/directions"

REAL Code Examples from goplaces

Let's examine actual patterns from the repository, with detailed commentary on how to wield them effectively.

Example 1: Filtered Text Search with Location Bias

The bread-and-butter operation: finding places with precise control.

# Search for highly-rated coffee near Columbia University
goplaces search "coffee" --min-rating 4 --open-now --limit 5 \
  --lat 40.8065 --lng -73.9719 --radius-m 3000 --language en --region US

What's happening here? The search command hits Google's Text Search endpoint. --min-rating 4 filters to quality establishments. --open-now is a lifesaver for user-facing applications — no one wants to arrive at a closed café. The location bias (--lat/--lng with --radius-m) prioritizes results near Columbia's campus without hard-restricting to that circle. --language en and --region US ensure consistent formatting for addresses and phone numbers. The --limit 5 caps results to keep responses snappy.

Example 2: Go Library — Structured Search with Filters

When you need goplaces inside your application, the Go API shines. Here's the canonical search pattern:

// Helper functions for pointer literals — Go's lack of generic pointer syntax
// makes these invaluable for optional filter fields
boolPtr := func(v bool) *bool { return &v }
floatPtr := func(v float64) *float64 { return &v }

// Initialize client with sensible timeout — network calls to Google
// should never hang indefinitely. 8 seconds balances reliability and responsiveness.
client := goplaces.NewClient(goplaces.Options{
    APIKey:  os.Getenv("GOOGLE_PLACES_API_KEY"), // Never hardcode secrets
    Timeout: 8 * time.Second,
})

// Execute search with rich filtering — this replaces ~50 lines of raw HTTP code
search, err := client.Search(ctx, goplaces.SearchRequest{
    Query: "italian restaurant",
    Filters: &goplaces.Filters{
        OpenNow:   boolPtr(true),      // Only currently open establishments
        MinRating: floatPtr(4.0),      // Quality threshold
        Types:     []string{"restaurant"}, // Maps to Google's includedType (first only)
    },
    LocationBias: &goplaces.LocationBias{
        Lat: 40.8065,      // Columbia University area
        Lng: -73.9719,
        RadiusM: 3000,     // 3km search radius
    },
    Language: "en",        // Consistent result language
    Region:   "US",        // Phone/address formatting
    Limit:    10,          // Paginate responsibly
})

Critical insight: The Filters.Types field maps to Google's includedType parameter, which only accepts a single value. goplaces handles this gracefully — only your first type is sent. The boolPtr and floatPtr helpers are idiomatic Go patterns for optional fields in struct literals; without them, you'd need verbose variable declarations.

Example 3: Place Details with Conditional Expansion

Sometimes you need the full picture. Here's how to fetch rich place data with optional reviews and photos:

// Fetch comprehensive place details with review expansion
// Note: reviews and photos cost additional quota — request only when needed
details, err := client.DetailsWithOptions(ctx, goplaces.DetailsRequest{
    PlaceID:        "ChIJN1t_tDeuEmsRUsoyG83frY4", // Sydney Opera House
    Language:       "en",
    Region:         "US",
    IncludeReviews: true,  // Explicit opt-in for review data
})

// Alternative: photo expansion for gallery applications
photoDetails, err := client.DetailsWithOptions(ctx, goplaces.DetailsRequest{
    PlaceID:        "ChIJN1t_tDeuEmsRUsoyG83frY4",
    Language:       "en",
    IncludePhotos:  true,  // Explicit opt-in for photo metadata
})

Performance note: Reviews and photos are expensive — both in quota and response size. goplaces forces explicit opt-in via IncludeReviews and IncludePhotos, protecting you from accidental over-fetching. The CLI mirrors this with --reviews and --photos flags.

Example 4: Route-Aware Place Discovery

This is where goplaces transcends typical API clients. The route command combines polyline sampling with place search:

# Find coffee shops along a driving route, sampled at up to 5 waypoints
goplaces route "coffee" --from "Seattle, WA" --to "Portland, OR" --max-waypoints 5

And the Go equivalent:

// Route search: combines Directions API polyline with Places Nearby Search
// Perfect for road trip planners, logistics optimization, or travel apps
route, err := client.Route(ctx, goplaces.RouteRequest{
    Query:        "coffee",           // What to search for
    From:         "Seattle, WA",      // Origin (geocoded automatically)
    To:           "Portland, OR",     // Destination (geocoded automatically)
    MaxWaypoints: 5,                  // Sampling density along route
})

The magic: Google calculates your driving route, samples it into waypoints, and searches near each. You get results that are actually on your way, not merely near the straight-line midpoint. This eliminates the classic "great rating, 20 miles off the highway" problem.

Example 5: Directions with Route Modifiers

For pure routing without place search:

# Walking directions with optional driving comparison
goplaces directions --from "Pike Place Market" --to "Space Needle"

# Driving with toll avoidance — critical for cost-sensitive logistics
goplaces directions --from "Paris" --to "Brest" --mode drive --avoid-tolls

# Multiple avoidance flags — highway and ferry aversion for scenic routing
goplaces directions --from "Paris" --to "Brest" --mode drive --avoid-highways --avoid-ferries

# Imperial units for US-based applications
goplaces directions --from "Pike Place Market" --to "Space Needle" --units imperial --steps

Important constraint: Route modifiers (--avoid-tolls, --avoid-highways, --avoid-ferries) require --mode drive. Walking and transit modes don't support these modifiers — Google silently ignores them, but goplaces documents this clearly to prevent confusion.

Advanced Usage & Best Practices

Pagination for Large Result Sets Google's Places API paginates at 20 results. Capture the next page token:

FIRST_PAGE=$(goplaces search "pizza" --json)
NEXT_TOKEN=$(echo $FIRST_PAGE | jq -r '.next_page_token')
goplaces search "pizza" --page-token "$NEXT_TOKEN"

Session Tokens for Autocomplete Always use session tokens for autocomplete to optimize billing:

goplaces autocomplete "cof" --session-token "user-session-$(date +%s)" --limit 5

Testing with E2E Suite Validate your integration against real APIs:

export GOOGLE_PLACES_API_KEY="..."
make e2e  # Full end-to-end validation

Customize test parameters via environment variables for targeted validation.

JSON Pipeline Patterns The --json flag enables powerful Unix philosophy workflows:

# Extract just names and ratings for a report
goplaces nearby --lat 47.6062 --lng -122.3321 --type restaurant --limit 20 --json | \
  jq -r '.[] | "\(.name): \(.rating)⭐"'

Comparison with Alternatives

Feature goplaces Official Google Client Custom HTTP Wrapper maps.googleapis.com Direct
CLI Experience ✅ Native, polished ❌ None ⚠️ Build your own ❌ Manual curl
Field Mask Handling ✅ Automatic ⚠️ Manual ❌ You implement ❌ Painful
JSON Output ✅ Built-in ❌ Library only ⚠️ Your code ⚠️ Raw parsing
Routes + Places Combo ✅ Native route ❌ Separate APIs ❌ Complex integration ❌ Multiple calls
Go Library ✅ Stable public API ✅ Official ❌ Maintenance burden ❌ None
Setup Complexity ✅ One binary ⚠️ Dependency management ❌ High ⚠️ Medium
Mock/Proxy Testing ✅ Base URL overrides ⚠️ Limited ⚠️ Your implementation ❌ Difficult

Verdict: goplaces wins on developer experience for CLI and scripting use cases. The official client makes sense for deep Google Cloud integration. Custom wrappers are technical debt. Direct HTTP calls are masochism.

FAQ

Q: Is goplaces free to use? A: The tool is open-source and free. However, Google's Places API (New) and Routes API have usage-based pricing. Always set quota limits and budget alerts in Google Cloud Console.

Q: Can I use goplaces in production Go services? A: Absolutely. The root package github.com/steipete/goplaces provides a stable public API. The v0.4.0 release indicates active development — pin to specific versions for stability.

Q: What's the difference between Places API and Places API (New)? A: Google launched a redesigned Places API with different endpoints, field masks, and pricing. goplaces exclusively targets the (New) version. Ensure you've enabled the correct API in Google Cloud.

Q: How do I handle API rate limits? A: goplaces respects Google's quotas. For high-volume applications, implement client-side backoff and cache aggressively. The --timeout flag helps prevent hanging requests during quota exhaustion.

Q: Can I contribute to goplaces? A: The repository at github.com/steipete/goplaces welcomes contributions. Run make lint test coverage before submitting PRs. E2E tests require a valid API key.

Q: Why are reviews and photos opt-in instead of default? A: These fields consume additional quota and significantly increase response size. goplaces follows the principle of minimal data fetching — request only what you need.

Q: Does goplaces support batch operations? A: Currently, batching requires multiple CLI invocations or Go API calls. Google's Places API (New) itself has limited native batch support compared to the legacy API.

Conclusion

The Google Places API (New) is powerful but punishing. goplaces transforms it from a chore into a delight — whether you're hacking in a terminal, building production Go services, or wiring location intelligence into AI agents.

Peter Steinberger has crafted something rare: a tool that respects both human and machine consumers. The CLI feels native to modern development workflows. The Go library integrates cleanly without abstraction bloat. And features like route-aware search solve real problems that generic API clients simply don't address.

If you're still hand-crafting field masks, parsing raw JSON, or maintaining fragile API wrappers, you're working too hard. Stop wrestling with Google Places. Start using goplaces.

Install it now, grab your API key, and experience what location data tooling should have been all along:

brew install steipete/tap/goplaces
# or
go install github.com/steipete/goplaces/cmd/goplaces@latest

Then explore the full documentation at goplaces.sh and star the repository at github.com/steipete/goplaces to follow development. Your future self — the one not debugging field mask syntax at 2 AM — will thank you.

Comments (0)

Comments are moderated before appearing.

No comments yet. Be the first to share your thoughts!

Support us! ☕