ipregistry

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 2, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

README

Ipregistry

Ipregistry Go Client Library

License Go Reference Go CI Lint

This is the official Go client library for the Ipregistry IP geolocation and threat data API, allowing you to look up your own IP address or specified ones. Responses return multiple data points including carrier, company, currency, location, time zone, threat information, and more. The library can also parse raw User-Agent strings.

The library has zero external dependencies — it is built entirely on the Go standard library.

Getting Started

You'll need an Ipregistry API key, which you can get along with 100,000 free lookups by signing up for a free account at https://ipregistry.co.

Installation
go get github.com/ipregistry/ipregistry-go

Requires Go 1.23 or later.

import ipregistry "github.com/ipregistry/ipregistry-go"
Quick start
Single IP lookup
package main

import (
	"context"
	"fmt"
	"log"

	ipregistry "github.com/ipregistry/ipregistry-go"
)

func main() {
	client := ipregistry.New("YOUR_API_KEY")
	defer client.Close()

	// Look up data for a given IPv4 or IPv6 address.
	// On the server side, retrieve the client IP from the request headers.
	info, err := client.Lookup(context.Background(), "54.85.132.205")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(info.Location.Country.Name)
}
Origin IP lookup

To look up the IP address the request is sent from — no argument needed — use LookupOrigin. It returns a RequesterIPInfo, which additionally carries parsed User-Agent data.

origin, err := client.LookupOrigin(context.Background())
if err != nil {
	log.Fatal(err)
}
fmt.Println(origin.IP, origin.Location.Country.Name)
Batch IP lookup

LookupBatch resolves many IP addresses in a single request. Each entry may independently succeed or fail (for example on an invalid address), so results are inspected element by element. Iterate with the All range-over-func, or index with At:

list, err := client.LookupBatch(context.Background(),
	[]string{"73.2.2.2", "8.8.8.8", "2001:67c:2e8:22::c100:68b"})
if err != nil {
	log.Fatal(err)
}

for info, err := range list.All() {
	if err != nil {
		// Handle a per-entry error (e.g. invalid IP address).
		log.Println("entry failed:", err)
		continue
	}
	fmt.Println(info.Location.Country.Name)
}

The Ipregistry API accepts up to 1024 IP addresses per request. LookupBatch transparently splits larger slices into several requests, dispatched with bounded concurrency, and reassembles the results in input order — so you can pass an arbitrarily long slice without hitting TOO_MANY_IPS. Tune the behavior when needed:

client := ipregistry.New("YOUR_API_KEY",
	ipregistry.WithMaxBatchSize(1024),      // addresses per request (max/default: 1024)
	ipregistry.WithBatchConcurrency(4),     // concurrent sub-requests (default: 4; 1 = sequential)
)

Only cache misses are sent to the API; if a whole sub-request fails (network or API error), LookupBatch returns that error, whereas an individual bad address surfaces as a per-entry error as shown above.

Typed IP addresses

IP addresses are passed as strings, which is how they usually arrive (for example from a request's X-Forwarded-For header). If you already hold a parsed net/netip.Addr, typed convenience methods are available and validate the address before sending the request:

addr := netip.MustParseAddr("8.8.8.8")
info, err := client.LookupAddr(context.Background(), addr)

addrs := []netip.Addr{netip.MustParseAddr("1.1.1.1"), netip.MustParseAddr("2606:4700:4700::1111")}
list, err := client.LookupBatchAddr(context.Background(), addrs)

Options

Lookups accept options that map to Ipregistry query parameters:

info, err := client.Lookup(context.Background(), "8.8.8.8",
	ipregistry.WithHostname(true),                            // resolve reverse-DNS hostname
	ipregistry.WithFields("location.country.name,security"),  // select only these fields
)
Option Description
WithHostname(bool) Enable reverse-DNS hostname resolution (disabled by default).
WithFields(expression) Restrict the response to the given fields, reducing payload size.
WithParam(name, value) Set an arbitrary query parameter not covered by a dedicated helper.

Caching

Although the client has built-in support for in-memory caching, it is disabled by default to ensure data freshness.

To enable caching, pass an InMemoryCache when constructing the client:

client := ipregistry.New("YOUR_API_KEY",
	ipregistry.WithCache(ipregistry.NewInMemoryCache()),
)

The in-memory cache is thread-safe and supports size- and time-based eviction (LRU with a TTL):

cache := ipregistry.NewInMemoryCache(
	ipregistry.WithMaxSize(8192),          // maximum number of entries (default 4096)
	ipregistry.WithTTL(10*time.Minute),    // entry lifetime (default 10 minutes)
)

client := ipregistry.New("YOUR_API_KEY", ipregistry.WithCache(cache))

Origin (requester) lookups are never cached, because the requester IP is only known from the response. Batch lookups transparently serve already-cached entries and only request the remainder from the API.

You can provide your own cache implementation by satisfying the Cache interface:

type Cache interface {
	Get(key string) (*IPInfo, bool)
	Set(key string, value *IPInfo)
	Invalidate(key string)
	InvalidateAll()
}

Retries

Failed requests are automatically retried with an exponential backoff. By default, up to 3 retries are performed on transient network errors and 5xx server responses.

Because Ipregistry does not rate limit by default (rate limiting is opt-in per API key), retries on 429 Too Many Requests responses are disabled by default. Enable them if your API key is configured with a rate limit and you want the client to wait and retry (honoring the Retry-After header when present):

client := ipregistry.New("YOUR_API_KEY",
	ipregistry.WithMaxRetries(3),                  // 0 disables retries entirely
	ipregistry.WithRetryInterval(time.Second),     // base backoff (interval * 2^attempt)
	ipregistry.WithRetryOnServerError(true),       // retry on 5xx (default: true)
	ipregistry.WithRetryOnTooManyRequests(true),   // retry on 429 (default: false)
)

Context, timeouts, and concurrency

Every method takes a context.Context, so cancellation and deadlines compose naturally with the rest of your program. There is no separate asynchronous API: a Client is safe for concurrent use, so run lookups in goroutines when you need parallelism.

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

info, err := client.Lookup(ctx, "8.8.8.8")

By default the client uses an http.Client with a 15-second timeout. Adjust it with WithTimeout, or supply your own client for full control over connection pooling, proxying, TLS, or instrumentation:

httpClient := &http.Client{ /* custom transport, proxy, TLS, timeout, ... */ }

client := ipregistry.New("YOUR_API_KEY", ipregistry.WithHTTPClient(httpClient))

When you supply your own client, you own its lifecycle: Client.Close does not touch it, and WithTimeout is ignored in favor of your client's own settings.

Errors

The library returns two typed error kinds, both matchable with errors.As:

  • *APIError — the API reported a failure (e.g. insufficient credits, throttling, invalid input). It carries the raw Code, a typed ErrorCode (empty when the raw code is not recognized), a Message, and a Resolution.
  • *ClientError — a client-side failure (network error, request cancellation, response decoding). The underlying cause is available via errors.Unwrap / errors.Is.
info, err := client.Lookup(context.Background(), "8.8.8.8")

var apiErr *ipregistry.APIError
var clientErr *ipregistry.ClientError
switch {
case errors.As(err, &apiErr):
	if apiErr.ErrorCode == ipregistry.ErrorCodeInsufficientCredits {
		// handle exhausted credits
	} else if apiErr.ErrorCode == ipregistry.ErrorCodeTooManyRequests {
		// handle rate limiting
	}
case errors.As(err, &clientErr):
	// handle network / decoding error
}

The full list of error codes is documented at ipregistry.co/docs/errors.

Parsing User-Agents

Parse one or more raw User-Agent strings (such as the User-Agent header of an incoming request) into structured data:

list, err := client.ParseUserAgents(context.Background(),
	"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/120.0")
if err != nil {
	log.Fatal(err)
}
ua, err := list.At(0)
if err != nil {
	log.Fatal(err)
}
fmt.Println(ua.Name, ua.OperatingSystem.Name)

Filtering bots

You might want to prevent Ipregistry API calls for crawlers or bots browsing your pages. To help identify bots from the User-Agent, the library includes a lightweight helper:

// For testing you can retrieve your current User-Agent from:
// https://api.ipregistry.co/user_agent?key=YOUR_API_KEY (look at the "user_agent" field)
if !ipregistry.IsBot(userAgentFromRequestHeader) {
	info, err := client.Lookup(context.Background(), clientIP)
	// ...
}

Examples

Runnable examples live in the examples/ directory. Each is a standalone main package; set your key and run it:

IPREGISTRY_API_KEY=YOUR_API_KEY go run ./examples/single

Testing

The library ships with two tiers of tests:

  • Unit / behavior tests run offline against an in-process net/http/httptest server — no API key or network is required. This is the default go test ./... and what CI runs (with the race detector and coverage).

  • System tests exercise the live Ipregistry API. They live behind the integration build tag and are skipped unless IPREGISTRY_API_KEY is set (each successful lookup consumes credits):

    IPREGISTRY_API_KEY=YOUR_API_KEY go test -tags integration -run Integration ./...
    

Common tasks are wired through the Makefile: make test, make race, make cover, make vet, make fmtcheck, make lint, and make integration.

Other Libraries

There are official Ipregistry client libraries available for many languages including Java, Javascript, Python, Typescript and more.

Are you looking for an official client with a programming language or framework we do not support yet? Let us know.

License

This library is released under the Apache 2.0 license.

Documentation

Overview

Package ipregistry is the official Go client library for the Ipregistry (https://ipregistry.co) IP geolocation and threat data API.

It lets you look up your own IP address or arbitrary ones. Responses return multiple data points including carrier, company, connection, currency, location, time zone, and threat information, and it can also parse raw User-Agent strings.

Getting started

You need an Ipregistry API key, which you can get along with a generous free tier by signing up at https://ipregistry.co.

client := ipregistry.New("YOUR_API_KEY")
defer client.Close()

info, err := client.Lookup(context.Background(), "8.8.8.8")
if err != nil {
	log.Fatal(err)
}
fmt.Println(info.Location.Country.Name)

Origin lookup

To retrieve data for the IP address the request originates from, use Client.LookupOrigin, which additionally returns parsed User-Agent data:

origin, err := client.LookupOrigin(context.Background())

Batch lookups

Client.LookupBatch resolves many IP addresses in a single request. Each entry may independently succeed or fail (for example on an invalid address), so results are inspected element by element:

list, err := client.LookupBatch(ctx, []string{"8.8.8.8", "1.1.1.1"})
if err != nil {
	log.Fatal(err)
}
for info, err := range list.All() {
	if err != nil {
		log.Println("entry failed:", err)
		continue
	}
	fmt.Println(info.Location.Country.Name)
}

Errors

API-level failures are reported as *APIError, which carries both the raw Ipregistry error code and a typed ErrorCode. Transport and decoding failures are reported as *ClientError. Both can be matched with errors.As.

Concurrency

A Client is safe for concurrent use by multiple goroutines. Because every method takes a context.Context, cancellation and timeouts compose naturally with Go's concurrency primitives; there is no separate asynchronous API.

Index

Examples

Constants

View Source
const DefaultBaseURL = "https://api.ipregistry.co"

DefaultBaseURL is the base URL of the Ipregistry API used unless overridden with WithBaseURL.

View Source
const DefaultMaxBatchSize = 1024

DefaultMaxBatchSize is the maximum number of IP addresses Ipregistry accepts in a single batch request. LookupBatch transparently splits larger slices into several requests so callers never have to.

View Source
const Version = "1.0.0"

Version is the released version of the client library. It is reported as part of the User-Agent header sent with every request to the Ipregistry API.

Variables

This section is empty.

Functions

func IsBot

func IsBot(userAgent string) bool

IsBot reports whether the given raw User-Agent string looks like a crawler or bot. It is a lightweight heuristic — useful for skipping IP lookups on automated traffic — that matches the substrings "bot", "spider", and "slurp" case-insensitively.

Example
package main

import (
	"fmt"

	ipregistry "github.com/ipregistry/ipregistry-go"
)

func main() {
	userAgent := "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
	if ipregistry.IsBot(userAgent) {
		fmt.Println("skip lookup for bot traffic")
	}
}
Output:
skip lookup for bot traffic

Types

type APIError

type APIError struct {
	// Code is the raw error code returned by the API.
	Code string
	// ErrorCode is the typed form of Code, or empty if Code is not recognized.
	ErrorCode ErrorCode
	// Message is a human-readable description of the error.
	Message string
	// Resolution suggests how to resolve the error, when available.
	Resolution string
}

APIError is returned when the Ipregistry API reports a failure, such as an invalid IP address, an exhausted credit balance, or throttling. It carries both the raw Code and, when recognized, the typed ErrorCode.

In batch lookups, an APIError may also describe the failure of a single entry rather than the whole request (see IPInfoList and UserAgentList).

func (*APIError) Error

func (e *APIError) Error() string

Error implements the error interface.

type Cache

type Cache interface {
	// Get returns the cached value for key, and whether it was present.
	Get(key string) (*IPInfo, bool)
	// Set stores value under key.
	Set(key string, value *IPInfo)
	// Invalidate removes the entry for key, if present.
	Invalidate(key string)
	// InvalidateAll removes every entry.
	InvalidateAll()
}

Cache abstracts the storage used by a Client to memoize IP lookups. Implementations must be safe for concurrent use by multiple goroutines.

Only successful single and batch IP lookups are cached. Origin lookups are never cached, because the requester IP is only known from the response.

type CacheOption

type CacheOption func(*InMemoryCache)

CacheOption customizes an InMemoryCache.

func WithMaxSize

func WithMaxSize(n int) CacheOption

WithMaxSize sets the maximum number of entries the cache holds before it starts evicting the least recently used entry. A value <= 0 leaves the default (4096).

func WithTTL

func WithTTL(d time.Duration) CacheOption

WithTTL sets how long an entry stays valid after being written. A value <= 0 leaves the default (10 minutes).

type Carrier

type Carrier struct {
	Name string `json:"name,omitempty"`
	// MCC is the Mobile Country Code.
	MCC string `json:"mcc,omitempty"`
	// MNC is the Mobile Network Code.
	MNC string `json:"mnc,omitempty"`
}

Carrier holds mobile carrier information associated with an IP address.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client sends requests to the Ipregistry API. Create one with New. A Client is safe for concurrent use by multiple goroutines.

Example (ErrorHandling)
package main

import (
	"context"
	"errors"
	"fmt"

	ipregistry "github.com/ipregistry/ipregistry-go"
)

func main() {
	client := ipregistry.New("YOUR_API_KEY")
	defer client.Close()

	_, err := client.Lookup(context.Background(), "8.8.8.8")

	var apiErr *ipregistry.APIError
	var clientErr *ipregistry.ClientError
	switch {
	case errors.As(err, &apiErr):
		if apiErr.ErrorCode == ipregistry.ErrorCodeInsufficientCredits {
			fmt.Println("out of credits")
		}
	case errors.As(err, &clientErr):
		fmt.Println("network or decoding error:", clientErr)
	}
}

func New

func New(apiKey string, opts ...Option) *Client

New creates a Client authenticating with the given API key. You can obtain a key, along with a generous free tier, at https://ipregistry.co.

By default the client manages its own *http.Client with a 15-second timeout, retries transient failures up to three times, and performs no caching. Behavior is customized with Option values.

Example (Caching)
package main

import (
	"context"
	"time"

	ipregistry "github.com/ipregistry/ipregistry-go"
)

func main() {
	client := ipregistry.New("YOUR_API_KEY",
		ipregistry.WithCache(ipregistry.NewInMemoryCache(
			ipregistry.WithMaxSize(8192),
			ipregistry.WithTTL(10*time.Minute),
		)),
	)
	defer client.Close()

	_, _ = client.Lookup(context.Background(), "8.8.8.8")
}

func (*Client) Cache

func (c *Client) Cache() Cache

Cache returns the cache used by the client.

func (*Client) Close

func (c *Client) Close() error

Close releases resources held by the client. When the client owns its *http.Client (the default), idle connections are closed. It is safe to call Close multiple times. A closed client should no longer be used.

func (*Client) Lookup

func (c *Client) Lookup(ctx context.Context, ip string, opts ...LookupOption) (*IPInfo, error)

Lookup returns the data associated with the given IP address. The ip argument must be a non-empty IPv4 or IPv6 address; to look up the requester's own IP, use LookupOrigin instead.

When a cache is configured, a hit is returned without contacting the API.

Example
package main

import (
	"context"
	"fmt"
	"log"

	ipregistry "github.com/ipregistry/ipregistry-go"
)

func main() {
	client := ipregistry.New("YOUR_API_KEY")
	defer client.Close()

	info, err := client.Lookup(context.Background(), "8.8.8.8")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(info.Location.Country.Name)
}
Example (WithOptions)
package main

import (
	"context"
	"fmt"
	"log"

	ipregistry "github.com/ipregistry/ipregistry-go"
)

func main() {
	client := ipregistry.New("YOUR_API_KEY")
	defer client.Close()

	info, err := client.Lookup(context.Background(), "8.8.8.8",
		ipregistry.WithHostname(true),
		ipregistry.WithFields("location.country.name,security"))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(info.Hostname, info.Security.IsThreat)
}

func (*Client) LookupAddr added in v1.1.0

func (c *Client) LookupAddr(ctx context.Context, addr netip.Addr, opts ...LookupOption) (*IPInfo, error)

LookupAddr returns the data associated with the given IP address. It is a typed convenience over Lookup for callers that already hold a netip.Addr (from net/netip); it fails fast with a *ClientError if addr is the zero value.

Most callers receive IP addresses as strings — for example from a request's X-Forwarded-For header — and can use Lookup directly.

func (*Client) LookupBatch

func (c *Client) LookupBatch(ctx context.Context, ips []string, opts ...LookupOption) (*IPInfoList, error)

LookupBatch resolves several IP addresses in a single request. The returned IPInfoList preserves the order of ips, and each entry may independently succeed or fail. A non-nil error indicates the whole request failed (for example authentication or a network error), not the failure of an individual entry.

Entries already present in the cache are served locally; only the remainder are requested from the API, and freshly resolved entries are cached.

Example
package main

import (
	"context"
	"fmt"
	"log"

	ipregistry "github.com/ipregistry/ipregistry-go"
)

func main() {
	client := ipregistry.New("YOUR_API_KEY")
	defer client.Close()

	list, err := client.LookupBatch(context.Background(),
		[]string{"73.2.2.2", "8.8.8.8", "2001:67c:2e8:22::c100:68b"})
	if err != nil {
		log.Fatal(err)
	}

	for info, err := range list.All() {
		if err != nil {
			log.Println("entry failed:", err)
			continue
		}
		fmt.Println(info.Location.Country.Name)
	}
}

func (*Client) LookupBatchAddr added in v1.1.0

func (c *Client) LookupBatchAddr(ctx context.Context, addrs []netip.Addr, opts ...LookupOption) (*IPInfoList, error)

LookupBatchAddr is the netip.Addr variant of LookupBatch. It fails fast with a *ClientError if any address is the zero value.

func (*Client) LookupOrigin

func (c *Client) LookupOrigin(ctx context.Context, opts ...LookupOption) (*RequesterIPInfo, error)

LookupOrigin returns the data associated with the IP address the request originates from, enriched with parsed User-Agent data. Origin lookups are never cached, because the requester IP is only known from the response.

Example
package main

import (
	"context"
	"fmt"
	"log"

	ipregistry "github.com/ipregistry/ipregistry-go"
)

func main() {
	client := ipregistry.New("YOUR_API_KEY")
	defer client.Close()

	origin, err := client.LookupOrigin(context.Background())
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(origin.IP, origin.Location.Country.Name)
}

func (*Client) ParseUserAgents

func (c *Client) ParseUserAgents(ctx context.Context, userAgents ...string) (*UserAgentList, error)

ParseUserAgents parses one or more raw User-Agent strings (such as the User-Agent header of an incoming HTTP request) into structured data. Results preserve the order of the input.

Example
package main

import (
	"context"
	"fmt"
	"log"

	ipregistry "github.com/ipregistry/ipregistry-go"
)

func main() {
	client := ipregistry.New("YOUR_API_KEY")
	defer client.Close()

	list, err := client.ParseUserAgents(context.Background(),
		"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/120.0")
	if err != nil {
		log.Fatal(err)
	}
	ua, err := list.At(0)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(ua.Name, ua.OperatingSystem.Name)
}

type ClientError

type ClientError struct {
	Message string
	Err     error
}

ClientError is returned for failures that occur on the client side rather than being reported by the API, such as network errors, request cancellation, or a response that cannot be decoded. The underlying cause, when any, is available through errors.Unwrap.

func (*ClientError) Error

func (e *ClientError) Error() string

Error implements the error interface.

func (*ClientError) Unwrap

func (e *ClientError) Unwrap() error

Unwrap returns the underlying cause, enabling errors.Is and errors.As.

type Company

type Company struct {
	Name   string      `json:"name,omitempty"`
	Domain string      `json:"domain,omitempty"`
	Type   CompanyType `json:"type,omitempty"`
}

Company holds ownership information for the IP address.

type CompanyType

type CompanyType string

CompanyType classifies the kind of company that owns an IP address.

const (
	CompanyTypeBusiness   CompanyType = "business"
	CompanyTypeEducation  CompanyType = "education"
	CompanyTypeGovernment CompanyType = "government"
	CompanyTypeHosting    CompanyType = "hosting"
	CompanyTypeISP        CompanyType = "isp"
)

type Connection

type Connection struct {
	// ASN is the Autonomous System Number, or nil when unknown.
	ASN          *int64         `json:"asn,omitempty"`
	Domain       string         `json:"domain,omitempty"`
	Organization string         `json:"organization,omitempty"`
	Route        string         `json:"route,omitempty"`
	Type         ConnectionType `json:"type,omitempty"`
}

Connection holds network connection information for the IP address.

type ConnectionType

type ConnectionType string

ConnectionType classifies the kind of network the IP address belongs to.

const (
	ConnectionTypeBusiness   ConnectionType = "business"
	ConnectionTypeEducation  ConnectionType = "education"
	ConnectionTypeGovernment ConnectionType = "government"
	ConnectionTypeHosting    ConnectionType = "hosting"
	ConnectionTypeInactive   ConnectionType = "inactive"
	ConnectionTypeISP        ConnectionType = "isp"
)

type Continent

type Continent struct {
	Code string `json:"code,omitempty"`
	Name string `json:"name,omitempty"`
}

Continent holds continent-level information for a location.

type Country

type Country struct {
	// Area is the total land area in square kilometers.
	Area float64 `json:"area"`
	// Borders lists the ISO 3166-1 alpha-2 codes of bordering countries.
	Borders     []string `json:"borders,omitempty"`
	CallingCode string   `json:"calling_code,omitempty"`
	Capital     string   `json:"capital,omitempty"`
	// Code is the ISO 3166-1 alpha-2 country code (for example "US").
	Code string `json:"code,omitempty"`
	Name string `json:"name,omitempty"`
	// Population is the estimated number of inhabitants.
	Population int `json:"population"`
	// PopulationDensity is the number of inhabitants per square kilometer.
	PopulationDensity float64    `json:"population_density"`
	Flag              Flag       `json:"flag"`
	Languages         []Language `json:"languages,omitempty"`
	// TLD is the country-code top-level domain (for example ".us").
	TLD string `json:"tld,omitempty"`
}

Country holds country-level information for a location.

type Currency

type Currency struct {
	Code         string         `json:"code,omitempty"`
	Name         string         `json:"name,omitempty"`
	NameNative   string         `json:"name_native,omitempty"`
	Plural       string         `json:"plural,omitempty"`
	PluralNative string         `json:"plural_native,omitempty"`
	Symbol       string         `json:"symbol,omitempty"`
	SymbolNative string         `json:"symbol_native,omitempty"`
	Format       CurrencyFormat `json:"format"`
}

Currency holds currency information for the IP address location.

type CurrencyFormat

type CurrencyFormat struct {
	DecimalSeparator string              `json:"decimal_separator,omitempty"`
	GroupSeparator   string              `json:"group_separator,omitempty"`
	Negative         CurrencyFormatAffix `json:"negative"`
	Positive         CurrencyFormatAffix `json:"positive"`
}

CurrencyFormat describes how monetary values are formatted for a currency.

type CurrencyFormatAffix

type CurrencyFormatAffix struct {
	Prefix string `json:"prefix"`
	Suffix string `json:"suffix"`
}

CurrencyFormatAffix holds the prefix and suffix applied around a formatted monetary value (for example the currency symbol and a sign).

type ErrorCode

type ErrorCode string

ErrorCode is a strongly typed Ipregistry API error code. It lets callers branch on error conditions without matching on raw strings. See https://ipregistry.co/docs/errors for the authoritative list.

const (
	ErrorCodeBadRequest          ErrorCode = "BAD_REQUEST"
	ErrorCodeDisabledAPIKey      ErrorCode = "DISABLED_API_KEY"
	ErrorCodeForbiddenIP         ErrorCode = "FORBIDDEN_IP"
	ErrorCodeForbiddenOrigin     ErrorCode = "FORBIDDEN_ORIGIN"
	ErrorCodeForbiddenIPOrigin   ErrorCode = "FORBIDDEN_IP_ORIGIN"
	ErrorCodeInternal            ErrorCode = "INTERNAL"
	ErrorCodeInsufficientCredits ErrorCode = "INSUFFICIENT_CREDITS"
	ErrorCodeInvalidAPIKey       ErrorCode = "INVALID_API_KEY"
	ErrorCodeInvalidASN          ErrorCode = "INVALID_ASN"
	ErrorCodeInvalidFilterSyntax ErrorCode = "INVALID_FILTER_SYNTAX"
	ErrorCodeInvalidIPAddress    ErrorCode = "INVALID_IP_ADDRESS"
	ErrorCodeMissingAPIKey       ErrorCode = "MISSING_API_KEY"
	ErrorCodeReservedASN         ErrorCode = "RESERVED_ASN"
	ErrorCodeReservedIPAddress   ErrorCode = "RESERVED_IP_ADDRESS"
	ErrorCodeTooManyASNs         ErrorCode = "TOO_MANY_ASNS"
	ErrorCodeTooManyIPs          ErrorCode = "TOO_MANY_IPS"
	ErrorCodeTooManyRequests     ErrorCode = "TOO_MANY_REQUESTS"
	ErrorCodeTooManyUserAgents   ErrorCode = "TOO_MANY_USER_AGENTS"
	ErrorCodeUnknownASN          ErrorCode = "UNKNOWN_ASN"
)

func ParseErrorCode

func ParseErrorCode(raw string) ErrorCode

ParseErrorCode maps a raw API error code to its typed ErrorCode. It returns an empty ErrorCode when the raw code is not recognized.

type Flag

type Flag struct {
	Emoji        string `json:"emoji,omitempty"`
	EmojiUnicode string `json:"emoji_unicode,omitempty"`
	Emojitwo     string `json:"emojitwo,omitempty"`
	Noto         string `json:"noto,omitempty"`
	Twemoji      string `json:"twemoji,omitempty"`
	Wikimedia    string `json:"wikimedia,omitempty"`
}

Flag holds representations of a country flag across several icon sets.

type IPInfo

type IPInfo struct {
	// IP is the IP address the data refers to.
	IP string `json:"ip,omitempty"`
	// Type is the IP version (IPv4, IPv6, or Unknown).
	Type IPType `json:"type,omitempty"`
	// Hostname is the reverse-DNS hostname, when hostname resolution is
	// requested (see WithHostname) and available.
	Hostname string `json:"hostname,omitempty"`

	Carrier    Carrier    `json:"carrier"`
	Company    Company    `json:"company"`
	Connection Connection `json:"connection"`
	Currency   Currency   `json:"currency"`
	Location   Location   `json:"location"`
	Security   Security   `json:"security"`
	TimeZone   TimeZone   `json:"time_zone"`
}

IPInfo holds the comprehensive set of information associated with an IP address returned by the Ipregistry API.

Nested objects (Carrier, Company, Connection, Currency, Location, Security, and TimeZone) are always present as values, so accessing their fields never panics even when the API omitted them; absent fields hold their zero value.

type IPInfoList

type IPInfoList struct {
	Results []IPInfoResult
}

IPInfoList holds the ordered results of a batch IP lookup. Each entry may independently succeed or fail; use At or All to inspect them.

func (*IPInfoList) All

func (l *IPInfoList) All() iter.Seq2[*IPInfo, error]

All returns an iterator over the entries in order, yielding either the resolved IPInfo or the error for each entry. It is intended for use with Go's range-over-func:

for info, err := range list.All() {
	if err != nil {
		// handle this entry's failure
		continue
	}
	// use info
}

func (*IPInfoList) At

func (l *IPInfoList) At(i int) (*IPInfo, error)

At returns the IPInfo at index i, or the error that entry failed with. It panics if i is out of range, matching slice indexing semantics.

func (*IPInfoList) Len

func (l *IPInfoList) Len() int

Len returns the number of entries in the list.

func (*IPInfoList) UnmarshalJSON

func (l *IPInfoList) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the {"results": [...]} envelope, mapping each element to either an IPInfo or an APIError depending on whether it carries an error code.

type IPInfoResult

type IPInfoResult struct {
	Info *IPInfo
	Err  *APIError
}

IPInfoResult is one entry of a batch lookup. Exactly one of Info and Err is non-nil: Info holds the data for a successfully resolved IP address, and Err describes why that particular entry failed.

type IPType

type IPType string

IPType denotes the version of an IP address.

const (
	IPTypeIPv4    IPType = "IPv4"
	IPTypeIPv6    IPType = "IPv6"
	IPTypeUnknown IPType = "Unknown"
)

type InMemoryCache

type InMemoryCache struct {
	// contains filtered or unexported fields
}

InMemoryCache is a thread-safe, in-process Cache with time-based expiration and a bounded size using least-recently-used eviction. The zero value is not usable; construct one with NewInMemoryCache.

func NewInMemoryCache

func NewInMemoryCache(opts ...CacheOption) *InMemoryCache

NewInMemoryCache creates an InMemoryCache. Without options it holds up to 4096 entries for 10 minutes each.

func (*InMemoryCache) Get

func (c *InMemoryCache) Get(key string) (*IPInfo, bool)

Get returns the cached value for key when present and unexpired.

func (*InMemoryCache) Invalidate

func (c *InMemoryCache) Invalidate(key string)

Invalidate removes the entry for key, if present.

func (*InMemoryCache) InvalidateAll

func (c *InMemoryCache) InvalidateAll()

InvalidateAll removes every entry.

func (*InMemoryCache) Len

func (c *InMemoryCache) Len() int

Len returns the current number of entries, including any not yet expired but possibly stale. It is primarily useful in tests.

func (*InMemoryCache) Set

func (c *InMemoryCache) Set(key string, value *IPInfo)

Set stores value under key, refreshing its expiration and evicting the least recently used entry if the cache is full.

type Language

type Language struct {
	Code string `json:"code,omitempty"`
	Name string `json:"name,omitempty"`
	// NativeName is the language's name in the language itself.
	NativeName string `json:"native,omitempty"`
}

Language holds language information.

type Location

type Location struct {
	Continent Continent `json:"continent"`
	Country   Country   `json:"country"`
	Region    Region    `json:"region"`
	City      string    `json:"city,omitempty"`
	Postal    string    `json:"postal,omitempty"`
	// Latitude is the decimal-degree latitude, or nil when unavailable.
	Latitude *float64 `json:"latitude,omitempty"`
	// Longitude is the decimal-degree longitude, or nil when unavailable.
	Longitude *float64 `json:"longitude,omitempty"`
	// Language is the primary language spoken at the location.
	Language Language `json:"language"`
	// InEU reports whether the location is within a European Union member state.
	InEU bool `json:"in_eu"`
}

Location holds the geographical location associated with an IP address.

type LookupOption

type LookupOption interface {
	// contains filtered or unexported methods
}

LookupOption customizes a single lookup or batch request by setting a query parameter. Construct options with WithFields, WithHostname, or WithParam.

func WithFields

func WithFields(expression string) LookupOption

WithFields restricts the response to the given fields, using Ipregistry's field selector syntax (for example "location.country.name,security"). This reduces payload size and, in some cases, credit usage. See https://ipregistry.co/docs/filtering-selecting-fields for the syntax.

func WithHostname

func WithHostname(enabled bool) LookupOption

WithHostname enables or disables reverse-DNS hostname resolution for the looked-up IP addresses. It is disabled by default.

func WithParam

func WithParam(name, value string) LookupOption

WithParam sets an arbitrary query parameter. Use it for options not covered by a dedicated helper.

type Option

type Option func(*Client)

Option configures a Client. Pass options to New.

func WithBaseURL

func WithBaseURL(baseURL string) Option

WithBaseURL overrides the API base URL. This is mainly useful for testing or pointing at a private deployment. A trailing slash is trimmed.

func WithBatchConcurrency

func WithBatchConcurrency(n int) Option

WithBatchConcurrency sets how many batch sub-requests LookupBatch dispatches concurrently when a slice is large enough to be split into chunks. A value <= 0 leaves the default (4). Set it to 1 for strictly sequential dispatch, which is gentler on a rate-limited API key.

func WithCache

func WithCache(cache Cache) Option

WithCache enables response caching using the supplied Cache. By default no cache is used so that data is never stale. Passing nil is a no-op.

func WithHTTPClient

func WithHTTPClient(httpClient *http.Client) Option

WithHTTPClient supplies a custom *http.Client, giving full control over connection pooling, proxying, TLS, and instrumentation. When set, the client's own Timeout takes precedence over WithTimeout, and the caller retains ownership: Client.Close does not close idle connections on a caller-provided client.

func WithMaxBatchSize

func WithMaxBatchSize(n int) Option

WithMaxBatchSize sets the maximum number of IP addresses sent in a single batch request. LookupBatch splits larger slices into this many addresses per request. Values are capped at DefaultMaxBatchSize (the API limit); a value <= 0 leaves the default.

func WithMaxRetries

func WithMaxRetries(n int) Option

WithMaxRetries sets the maximum number of automatic retries performed in addition to the initial attempt. Set to 0 to disable retries. Defaults to 3.

func WithRetryInterval

func WithRetryInterval(d time.Duration) Option

WithRetryInterval sets the base backoff between retries. Successive retries use an exponentially increasing delay (interval * 2^attempt). When a 429 response carries a Retry-After header, that value takes precedence. Defaults to 1 second.

func WithRetryOnServerError

func WithRetryOnServerError(enabled bool) Option

WithRetryOnServerError controls whether 5xx responses (and transient network errors) are retried. Defaults to true.

func WithRetryOnTooManyRequests

func WithRetryOnTooManyRequests(enabled bool) Option

WithRetryOnTooManyRequests controls whether 429 Too Many Requests responses are retried, honoring the Retry-After header when present. Ipregistry does not rate limit by default (it is opt-in per API key), so this defaults to false.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout sets the per-request timeout applied to the default HTTP client. It is ignored when a custom client is provided with WithHTTPClient. A value <= 0 disables the client-level timeout (rely on the request context instead).

func WithUserAgent

func WithUserAgent(ua string) Option

WithUserAgent overrides the User-Agent header sent with requests.

type Region

type Region struct {
	// Code is typically the ISO 3166-2 subdivision code.
	Code string `json:"code,omitempty"`
	Name string `json:"name,omitempty"`
}

Region holds administrative region (state/province) information.

type RequesterIPInfo

type RequesterIPInfo struct {
	IPInfo
	// UserAgent holds the parsed User-Agent of the requester, or nil when the
	// API did not return any.
	UserAgent *UserAgent `json:"user_agent,omitempty"`
}

RequesterIPInfo enriches IPInfo with parsed User-Agent data. It is returned by Client.LookupOrigin, where the User-Agent of the calling client is known.

type Security

type Security struct {
	IsAbuser        bool `json:"is_abuser"`
	IsAttacker      bool `json:"is_attacker"`
	IsBogon         bool `json:"is_bogon"`
	IsCloudProvider bool `json:"is_cloud_provider"`
	IsProxy         bool `json:"is_proxy"`
	IsRelay         bool `json:"is_relay"`
	IsTor           bool `json:"is_tor"`
	IsTorExit       bool `json:"is_tor_exit"`
	IsAnonymous     bool `json:"is_anonymous"`
	IsThreat        bool `json:"is_threat"`
	IsVPN           bool `json:"is_vpn"`
}

Security holds threat-intelligence flags for the IP address.

type TimeZone

type TimeZone struct {
	ID           string `json:"id,omitempty"`
	Abbreviation string `json:"abbreviation,omitempty"`
	CurrentTime  string `json:"current_time,omitempty"`
	Name         string `json:"name,omitempty"`
	// Offset is the current offset from UTC in seconds.
	Offset           int  `json:"offset"`
	InDaylightSaving bool `json:"in_daylight_saving"`
}

TimeZone holds time zone information for the IP address location.

type UserAgent

type UserAgent struct {
	// Header is the raw User-Agent string that was parsed.
	Header          string                   `json:"header,omitempty"`
	Name            string                   `json:"name,omitempty"`
	Type            string                   `json:"type,omitempty"`
	Version         string                   `json:"version,omitempty"`
	VersionMajor    string                   `json:"version_major,omitempty"`
	Device          UserAgentDevice          `json:"device"`
	Engine          UserAgentEngine          `json:"engine"`
	OperatingSystem UserAgentOperatingSystem `json:"os"`
}

UserAgent holds the structured data parsed from a raw User-Agent string.

type UserAgentDevice

type UserAgentDevice struct {
	Brand string `json:"brand,omitempty"`
	Name  string `json:"name,omitempty"`
	Type  string `json:"type,omitempty"`
}

UserAgentDevice holds the device data parsed from a User-Agent string.

type UserAgentEngine

type UserAgentEngine struct {
	Name         string `json:"name,omitempty"`
	Type         string `json:"type,omitempty"`
	Version      string `json:"version,omitempty"`
	VersionMajor string `json:"version_major,omitempty"`
}

UserAgentEngine holds the layout-engine data parsed from a User-Agent string.

type UserAgentList

type UserAgentList struct {
	Results []UserAgentResult
}

UserAgentList holds the ordered results of a User-Agent parse request.

func (*UserAgentList) All

func (l *UserAgentList) All() iter.Seq2[*UserAgent, error]

All returns an iterator over the entries in order, yielding either the parsed UserAgent or the error for each entry.

func (*UserAgentList) At

func (l *UserAgentList) At(i int) (*UserAgent, error)

At returns the UserAgent at index i, or the error that entry failed with. It panics if i is out of range, matching slice indexing semantics.

func (*UserAgentList) Len

func (l *UserAgentList) Len() int

Len returns the number of entries in the list.

func (*UserAgentList) UnmarshalJSON

func (l *UserAgentList) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the {"results": [...]} envelope, mapping each element to either a UserAgent or an APIError depending on whether it carries an error code.

type UserAgentOperatingSystem

type UserAgentOperatingSystem struct {
	Name    string `json:"name,omitempty"`
	Type    string `json:"type,omitempty"`
	Version string `json:"version,omitempty"`
}

UserAgentOperatingSystem holds the OS data parsed from a User-Agent string.

type UserAgentResult

type UserAgentResult struct {
	UserAgent *UserAgent
	Err       *APIError
}

UserAgentResult is one entry of a batch User-Agent parse. Exactly one of UserAgent and Err is non-nil.

Directories

Path Synopsis
examples
batch command
Command batch performs a batch lookup with in-memory caching enabled.
Command batch performs a batch lookup with in-memory caching enabled.
origin command
Command origin looks up the IP address the request originates from and prints the parsed User-Agent data returned alongside it.
Command origin looks up the IP address the request originates from and prints the parsed User-Agent data returned alongside it.
single command
Command single performs a single IP address lookup.
Command single performs a single IP address lookup.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL