SDKs
Markdown

Go SDK

Official IPScope server-side client for Go 1.22+ (github.com/ipscope-io/ipscope-go).

# Install

Install
go get github.com/ipscope-io/ipscope-go

# Quickstart: single, batch & prefix lookups

Pass your API key explicitly or set IPSCOPE_KEY in your environment. Every lookup returns the canonical response schema with geo, network, connection, security and security_extensions.

Go
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/ipscope-io/ipscope-go"
)

func main() {
	client := ipscope.NewClient(ipscope.Config{
		APIKey: os.Getenv("IPSCOPE_KEY"),
	})
	defer client.Close()

	ctx := context.Background()

	// 1. Single IPv4 or IPv6 lookup
	info, err := client.LookupIP(ctx, "198.51.100.7", nil)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s (%s) ASN=%d VPN=%v\n",
		info.IP, *info.Geo.CountryCode, *info.Network.ASN, info.Security.IsVPN)

	// 2. Batch lookup (up to 100 IPs; deduplicated & cached)
	batch, err := client.LookupBatch(ctx, []string{"198.51.100.7", "1.1.1.1"}, nil)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Resolved %d records\n", batch.Count)

	// 3. Network CIDR lookup
	netInfo, err := client.LookupNetwork(ctx, "198.51.100.0/24")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Prefix %s -> AS%d (%s)\n", netInfo.QueriedCIDR, *netInfo.Record.ASN, *netInfo.Record.Organization)
}
Responses
application/json

1. Single IPv4/IPv6 lookup response (GET /v1/ip/{ip})

{
  "ip": "198.51.100.7",
  "ip_version": 4,
  "matched_network": "198.51.100.0/24",
  "geo": {
    "country_code": "US",
    "declared_country_code": "US",
    "physical_country_code": "US",
    "is_virtual_location": false,
    "location_type": "physical",
    "confidence": 0.94,
    "subdivision": "Virginia",
    "city": "Ashburn",
    "postal_code": "20147",
    "latitude": 39.0438,
    "longitude": -77.4874,
    "accuracy_radius_km": 10,
    "timezone": "America/New_York"
  },
  "network": {
    "asn": 64501,
    "organization": "Example Cloud LLC"
  },
  "connection": {
    "connection_type": "hosting",
    "is_hosting": true,
    "is_residential": false,
    "is_mobile": false,
    "is_business": false
  },
  "security": {
    "is_vpn": true,
    "is_hosting": true,
    "is_tor_exit": false,
    "is_proxy": false,
    "anonymizer_type": "vpn",
    "confidence": 0.96,
    "reason_codes": [
      "vpn_handshake_confirmed",
      "datacenter_asn_range"
    ]
  },
  "security_extensions": {
    "abuse_velocity_score": 18,
    "is_known_scanner": false,
    "observation_recency_hours": 12,
    "anonymizer_reason": "vpn_handshake_confirmed",
    "threat_level": "medium",
    "abuse_velocity": "low",
    "confidence": 0.96
  },
  "dataset_version": "2026-10-27T00:00:00Z.crawl-1793088000000",
  "updated_at": "2026-10-27T00:00:00Z"
}
application/json

4. Network CIDR prefix lookup response (GET /v1/networks/{prefix}/{length})

{
  "queried_cidr": "198.51.100.0/24",
  "family": 4,
  "dataset_version": "2026-10-27T00:00:00Z.crawl-1793088000000",
  "record": {
    "prefix": "198.51.100.0/24",
    "family": 4,
    "asn": 64501,
    "organization": "Example Cloud LLC",
    "countryCode": "US",
    "city": "Ashburn",
    "locationType": "physical",
    "isVpn": true,
    "isHosting": true,
    "isTorExit": false,
    "isProxy": false,
    "anonymizerType": "vpn"
  }
}

# Architecture & runtime guarantees

  • Zero external dependencies (net/http, encoding/json, context, sync only), resulting in zero supply-chain bloat in go.mod.
  • Thread-safe doubly-linked list + hash map LRU cache protected by a fine-grained mutex.
  • LookupBatchStream callback API processes arbitrarily large IP slices in 100-IP chunks without allocating intermediate slice copies.
  • Context-aware cancellation and io.LimitReader response-body bounding (2 MiB ceiling) on every HTTP call.

# Reading local MMDB files

If you subscribe to a downloadable database, our .mmdb snapshots open directly in standard MaxMind DB readers with sub-microsecond in-memory lookups:

Go (MMDB)
db, err := maxminddb.Open("/var/lib/ipscope/ipscope-complete.mmdb")
if err != nil {
	log.Fatal(err)
}
defer db.Close()

var record map[string]any
err = db.Lookup(net.ParseIP("198.51.100.7"), &record)

# Plain HTTP fallback

Need to call the REST API without installing a package? Use Go’s standard HTTP client directly:

Go (HTTP)
req, _ := http.NewRequestWithContext(ctx, http.MethodGet,
	"https://api.ipscope.io/v1/ip/198.51.100.7", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("IPSCOPE_KEY"))

res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()

var info map[string]any
err = json.NewDecoder(res.Body).Decode(&info)