C# / .NET library

macadress.com for C#.

A typed .NET 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. CancellationToken on every call, targets netstandard2.0.

Package: Macadress on NuGet. Targets netstandard2.0 (.NET Framework 4.6.1+, .NET Core 2+, .NET 5+), MIT licensed, one dependency (System.Text.Json). Source at github.com/sapisos/macadress-csharp.

Install

dotnet add package Macadress

Look up a vendor

The name-only lookup needs no API key:

using Macadress;

var mac = new MacadressClient(); // keyless

await mac.VendorAsync("00:03:93:AB:12:34"); // "Apple, Inc."
await mac.VendorAsync("02:1a:2b:3c:4d:5e"); // "" (unregistered, private, or randomized)

Full analysis

Everything else needs a free API key:

var mac = new MacadressClient("mk_live_xxx");

var r = await mac.LookupAsync("3C:22:FB:12:34:56");

r.Organization;             // string?
r.Country;                  // "US"
r.BlockType;                // BlockType.MAL
r.PotentiallyRandomized;    // bool
r.RandomizationConfidence;  // RandomizationConfidence.None | Possible | Likely
r.Eui64;                    // "3E:22:FB:FF:FE:12:34:56"
r.Device.Category;          // DeviceCategory.Unknown (usually)
r.Explanation;               // plain-English summary

// anything not covered by a property is still reachable
r.TryGet("vendor_location.city", out var city); // (bool, JsonElement)
r.Raw;                                          // JsonElement

Batch and directory search

var items = await mac.BatchAsync(new[] { "00:03:93:00:00:00", "3C:22:FB:00:00:00", "bad" });
foreach (var it in items)
{
    Console.WriteLine(it.Failed ? $"{it.Input} -> {it.Error}" : $"{it.Input} -> {it.Organization}");
}

var hits = await mac.SearchVendorsAsync("Cisco", country: "US", limit: 20);
foreach (var b in hits.Blocks)
{
    Console.WriteLine($"{b.Organization} ({b.Country})");
}

BatchAsync throws ArgumentException without making a request if the list is empty or longer than MacadressClient.MaxBatchSize (100).

Errors

API error responses come back as ApiException (with StatusCode, Message, RequestId, RetryAfter and the decoded Body); a failure to reach the API at all is a MacadressTransportException. The common cases are distinguished by ApiException.Kind: ApiErrorKind.InvalidMac (400), ApiErrorKind.Auth (401), ApiErrorKind.RateLimited (429), ApiErrorKind.Quota (429).

try
{
    var r = await mac.LookupAsync(input);
}
catch (ApiException ex) when (ex.Kind == ApiErrorKind.RateLimited)
{
    await Task.Delay(ex.RetryAfter ?? TimeSpan.FromSeconds(1));
}
catch (ApiException ex) when (ex.Kind == ApiErrorKind.InvalidMac)
{
    // caller mistake, never billed
}

Concurrency and configuration

A MacadressClient is safe for concurrent use. Configure it with MacadressClientOptions: BaseUrl (for a self-hosted deployment), HttpClient, Timeout, UserAgent. Cancellation flows through the CancellationToken you pass to each call.

Quota

Each LookupAsync, BatchAsync address, and SearchVendorsAsync call is one API call against your plan, the same as a direct REST call: see pricing. The keyless VendorAsync endpoint is free for 1,000 lookups a day per IP; passing a key lifts that to your plan quota.

Links