Go library
macadress.com for Go.
A typed Go client for the MAC address and OUI vendor lookup API: vendor name, IEEE block, country, address type, EUI-64 / IPv6 derivation, randomization confidence and a device guess. Standard library only, context.Context on every call.
macadress. Go 1.23+, MIT licensed, no dependencies outside the standard library. Source at github.com/sapisos/macadress-go.
Install
go get github.com/sapisos/macadress-go
Look up a vendor
The name-only lookup needs no API key:
import macadress "github.com/sapisos/macadress-go"
mac := macadress.New("") // keyless
name, _ := mac.Vendor(ctx, "00:03:93:AB:12:34") // "Apple, Inc."
name, _ = mac.Vendor(ctx, "02:1a:2b:3c:4d:5e") // "" (unregistered, private, or randomized)
Full analysis
Everything else needs a free API key:
mac := macadress.New("mk_live_xxx")
r, err := mac.Lookup(ctx, "3C:22:FB:12:34:56")
r.Organization // string
r.Country // "US"
r.BlockType // macadress.BlockMAL
r.PotentiallyRandomized // bool
r.RandomizationConfidence // macadress.RandomizationNone | Possible | Likely
r.EUI64 // "3E:22:FB:FF:FE:12:34:56"
r.Device.Category // macadress.DeviceUnknown (usually)
r.Explanation // plain-English summary
// anything not covered by a struct field is still reachable
r.Get("vendor_location.city") // (any, bool)
r.Raw // map[string]any
Batch and directory search
items, _ := mac.Batch(ctx, []string{"00:03:93:00:00:00", "3C:22:FB:00:00:00", "bad"})
for _, it := range items {
if it.Failed() {
fmt.Printf("%s -> %s\n", it.Input, it.Err)
} else {
fmt.Printf("%s -> %s\n", it.Input, it.Organization)
}
}
hits, _ := mac.SearchVendors(ctx, "Cisco", macadress.WithCountry("US"), macadress.WithLimit(20))
for _, b := range hits.Blocks {
fmt.Printf("%s (%s)\n", b.Organization, b.Country)
}
Batch returns an error without making a request if the slice is empty or longer than macadress.MaxBatchSize (100).
Errors
API error responses come back as *macadress.APIError (with StatusCode, Message, RequestID, RetryAfter and the decoded Body); a failure to reach the API at all is a *macadress.TransportError. The common cases match sentinels with errors.Is: ErrInvalidMAC (400), ErrAuth (401), ErrRateLimited (429), ErrQuota (429, also matches ErrRateLimited).
r, err := mac.Lookup(ctx, input)
switch {
case errors.Is(err, macadress.ErrRateLimited):
var apiErr *macadress.APIError
errors.As(err, &apiErr)
time.Sleep(apiErr.RetryAfter)
case errors.Is(err, macadress.ErrInvalidMAC):
// caller mistake, never billed
}
Concurrency and configuration
A *macadress.Client is safe for concurrent use. Options: WithBaseURL (for a self-hosted deployment), WithHTTPClient, WithTimeout, WithUserAgent. Cancellation and deadlines flow through the context.Context you pass to each call.
Quota
Each Lookup, Batch address, and SearchVendors call is one API call against your plan, the same as a direct REST call: see pricing. The keyless Vendor endpoint is free for 1,000 lookups a day per IP; passing a key lifts that to your plan quota.
Links
- Package docs: pkg.go.dev/github.com/sapisos/macadress-go
- Source and issues: github.com/sapisos/macadress-go
- API reference: macadress.com/docs