Go SDK · Feature

Errors, Rate Limits & Usage

Every method returns (*T, error) and the client never retries — you stay in control of back-off. It also exposes your current quota so you can throttle before you hit a limit, and aggregate usage for dashboards and alerts.

Trusted by thousands of businesses
Fast JSON API responses
Real-time validation
Simple integration, SDKs & examples
What it does

Predictable failures, no hidden retries

Network calls fail — keys expire, quotas run out, servers hiccup. The SDK turns each HTTP status into a specific error type you can match with errors.As, and deliberately leaves retry policy to you, so a burst of failures can't silently multiply your request volume. When you do hit a rate limit, the error tells you exactly when the quota resets.

Prerequisites

1

Match typed errors with errors.As

Every typed error embeds *APIError, which carries StatusCode, Message and Body. Match the specific type you care about.

import "errors"

info, err := client.LookupIP(ctx, "8.8.8.8")
if err != nil {
	var rateErr *ipapi.RateLimitError
	var authErr *ipapi.AuthenticationError
	var invErr *ipapi.InvalidRequestError
	var srvErr *ipapi.ServerError
	switch {
	case errors.As(err, &rateErr):
		fmt.Printf("quota hit — resets at %d\n", rateErr.Reset)
	case errors.As(err, &authErr):
		fmt.Println("check your API key")
	case errors.As(err, &invErr):
		fmt.Println("bad request:", invErr.Message)
	case errors.As(err, &srvErr):
		fmt.Println("ip-api.io is having trouble, try later")
	default:
		fmt.Println("transport / decode error:", err)
	}
	return
}
fmt.Println(info.IP)
Transport failures (DNS, connect, timeout, decode) are returned as wrapped standard errors, not an *APIError — they fall through to the default branch above.
2

Handle rate limits with RateLimitError

On HTTP 429 you get *RateLimitError, carrying the x-ratelimit-* header values (-1 when a header is absent). Because the client never retries, Reset tells you when to.

var rateErr *ipapi.RateLimitError
if errors.As(err, &rateErr) {
	fmt.Println(rateErr.Limit)     // your quota for the window
	fmt.Println(rateErr.Remaining) // requests left (0 here)
	fmt.Println(rateErr.Reset)     // unix timestamp when quota renews
	// schedule a retry at rateErr.Reset instead of hammering the API
}
3

Check quota proactively with RateLimit

Read your current limits without triggering a 429, so you can throttle in advance.

rl, _ := client.RateLimit(ctx)

if rl.PlanName != nil {
	fmt.Println(*rl.PlanName)
}
fmt.Printf("%d / %d\n", rl.IPAPI.Remaining, rl.IPAPI.Limit)
fmt.Printf("%.1f%% used\n", rl.EmailAPI.UsagePercent)
4

Account usage with UsageSummary

Aggregate usage for the current period — handy for dashboards and internal alerts.

usage, _ := client.UsageSummary(ctx)

fmt.Println(usage.TotalRequests, usage.SuccessfulRequests)
fmt.Println(usage.RateLimitedRequests, usage.QuotaConsumed)
fmt.Println(usage.PeriodStart, usage.PeriodEnd)
Reference

Error taxonomy

TypeHTTP statusMeaning
*AuthenticationError401, 403Missing or invalid API key
*RateLimitError429Quota exhausted; exposes Limit, Remaining, Reset
*InvalidRequestError400, 404, 422Malformed input or unknown resource
*ServerError5xxip-api.io server-side failure
*APIErrorotherBase / fallback (carries StatusCode, Message, Body)
FAQ

Frequently asked questions

How do I handle errors from the ip-api.io SDK in Go?

Every method returns (*T, error). Use errors.As to match the typed error: *AuthenticationError (401/403), *RateLimitError (429), *InvalidRequestError (400/404/422), *ServerError (5xx), or the base *APIError. Transport failures fall through as wrapped standard errors.

Does the SDK retry failed requests automatically?

No. The client never retries — you stay in control of back-off. On a 429, RateLimitError.Reset gives the unix timestamp when your quota renews, so you can schedule a retry instead of hammering the API.

How do I check my remaining quota before hitting a limit?

Call client.RateLimit(ctx). It returns PlanID, PlanName, and IPAPI / EmailAPI blocks with Limit, Remaining, Used and UsagePercent, plus IntervalSeconds and NextRenewalDate.

What does RateLimitError expose?

*RateLimitError is parsed from the x-ratelimit-* response headers and exposes Limit (quota for the window), Remaining (requests left), and Reset (unix timestamp when quota renews). Headers absent? The value is -1.

Start building with the ip-api.io Go SDK

Run go get github.com/ip-api-io/ipapi-go, drop in your free API key, and ship in minutes — one typed, context-aware client for geolocation, fraud detection, and email validation.

Need support?

Explore how IP-API.io can enhance your security, provide robust bot protection, and improve IP geolocation accuracy for your applications.

Contact Support

Found a bug in the SDK?

The ipapi-go module is open source. Open an issue or pull request on GitHub and we'll take a look.

Open on GitHub