JavaScript library
macadress.com for JavaScript.
A typed JavaScript and TypeScript 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. Zero dependencies, runs anywhere there is fetch.
Install
npm install macadress # Node, Bun, bundlers
deno add jsr:@macadress/macadress # Deno
Or import straight from a CDN in the browser: import { Client } from "https://esm.sh/macadress".
Look up a vendor
The name-only lookup needs no API key:
import { Client } from "macadress";
const macadress = new Client();
await macadress.vendor("00:03:93:AB:12:34"); // "Apple, Inc."
await macadress.vendor("02:1a:2b:3c:4d:5e"); // null (unregistered, private, or randomized)
Full analysis
Everything else needs a free API key. Typed getters are properties, not calls:
const macadress = new Client("mk_live_xxx");
const r = await macadress.lookup("3C:22:FB:12:34:56");
r.organization; // string | null
r.country; // "US" | null
r.blockType; // "MA-L" | "MA-M" | "MA-S" | "IAB" | "CID" | null
r.isPotentiallyRandomized; // boolean
r.randomizationConfidence; // "none" | "possible" | "likely"
r.eui64; // "3E:22:FB:FF:FE:12:34:56" | null
r.device.category; // "unknown" (usually)
r.explanation; // plain-English summary
// anything not covered by a typed getter is still reachable
r.get("vendor_location.city");
r.raw;
Batch and directory search
for (const item of await macadress.batch(["00:03:93:00:00:00", "3C:22:FB:00:00:00", "bad"])) {
console.log(item.failed ? `${item.input} -> ${item.error}` : `${item.input} -> ${item.organization}`);
}
const hits = await macadress.searchVendors("Cisco", { country: "US", limit: 20 });
for (const block of hits) {
console.log(`${block.organization} (${block.country})`);
}
Errors
Every failure is an instance of MacadressError: InvalidMacError (400), AuthenticationError (401), RateLimitError (429, with .retryAfter), QuotaExceededError, TransportError for a network failure. Each carries .statusCode, .requestId and .responseBody.
import { Client, RateLimitError } from "macadress";
try {
const r = await macadress.lookup(input);
} catch (error) {
if (error instanceof RateLimitError) {
await new Promise((wake) => setTimeout(wake, (error.retryAfter ?? 5) * 1000));
} else {
throw error;
}
}
Runtimes
The client calls the platform fetch, so it runs unchanged on Node.js 18+, Deno, Bun, Cloudflare Workers and browsers. On an older runtime, pass your own implementation: new Client("mk_live_xxx", { fetch: myFetch }). TypeScript types are bundled; no @types package to install.
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: npmjs.com/package/macadress
- Deno / JSR: jsr.io/@macadress/macadress
- Source and issues: github.com/sapisos/macadress-js
- API reference: macadress.com/docs