MAC vendor lookup

From Rosetta Code
Task
MAC vendor lookup
You are encouraged to solve this task according to the task description, using any language you may know.

Every connected device around the world comes with a unique Media Access Control address, or a   MAC address.

A common task a network administrator may come across is being able to identify a network device's manufacturer when given only a MAC address.


Task

Interface with one (or numerous) APIs that exist on the internet and retrieve the device manufacturer based on a supplied MAC address.

A MAC address that does not return a valid result should return the String "N/A".   An error related to the network connectivity or the API should return a null result.

Many implementations on this page use http://api.macvendors.com/ which, as of 19th September 2021, is throttling requests. After only 2 calls, the following response is returned for all subsequent requests. If you are planning to use the same provider or going to run the examples on this page, consider building in a delay between two calls.

{"errors":{"detail":"Too Many Requests","message":"Please slow down your requests or upgrade your plan at https://macvendors.com"}}

Ada[edit]

Library: AWS
with Ada.Text_IO;

with AWS.Client;
with AWS.Response;
with AWS.Messages;

procedure MAC_Vendor is

   procedure Lookup (MAC : in String) is
      use AWS.Response;
      use AWS.Messages;
      URL     : constant String := "http://api.macvendors.com/" & MAC;
      Page    : constant Data   := AWS.Client.Get (URL);
      use Ada.Text_IO;
   begin
      Put (MAC);
      Set_Col (20);
      case AWS.Response.Status_Code (Page) is
         when S200   => Put_Line (Message_Body (Page));
         when S404   => Put_Line ("N/A");
         when others => Put_Line ("Error");
      end case;
   end Lookup;

begin
   --  Have to throttle traffic to site
   Lookup ("88:53:2E:67:07:BE");   delay 1.500;
   Lookup ("D4:F4:6F:C9:EF:8D");   delay 1.500;
   Lookup ("FC:FB:FB:01:FA:21");   delay 1.500;
   Lookup ("4c:72:b9:56:fe:bc");   delay 1.500;
   Lookup ("00-14-22-01-23-45");   delay 1.500;
   Lookup ("23-45-67");            delay 1.500;
   Lookup ("foobar");
end MAC_Vendor;
Output:
88:53:2E:67:07:BE  Intel Corporate
D4:F4:6F:C9:EF:8D  Apple, Inc.
FC:FB:FB:01:FA:21  Cisco Systems, Inc
4c:72:b9:56:fe:bc  PEGATRON CORPORATION
00-14-22-01-23-45  Dell Inc.
23-45-67           N/A
foobar             N/A

APL[edit]

Works with: Dyalog APL
Library: HttpCommand

Normally something like this would just be mapping the lookup across an array, but that doesn't let us control the timing of the request dispatch. To insert a delay between requests we have to create a traditional function ("tradfn") with a for loop.

⍝load the library module
]load HttpCommand

⍝ define a direct function (dfn) to look up a single MAC address
vendorLookup1  { (HttpCommand.Get 'http://api.macvendors.com/',⍕).Data }

⍝ define a traditional function to look up all the MAC addresses in a list with
⍝ a delay between calls

⍝ The header says that the function is named vendorLookup, it takes a single
⍝ parameter which we call macList, and the value of the local variable
⍝ vendors will become the function's return value
 vendors   vendorLookup macList 
    ⍝ look up the first vendor and put it into an array in our return var
    vendors  vendorLookup1 1macList
    
    ⍝ Loop over the rest of the array
    :For burger :In 1macList
       ⎕DL 2                              ⍝ wait 2 seconds
       vendors  vendorLookup1 burger   ⍝ then look up the next vendor and append
    :EndFor


⍝ demo data
macList   '88:53:2E:67:07:BE' 'D4:F4:6F:C9:EF:8D' 'FC:FB:FB:01:FA:21' 
macList  '4c:72:b9:56:fe:bc' '00-14-22-01-23-45'

⍝ look up the vendors (takes a while with the 2-second delay between lookups)
vendorList  vendorLookup macList

⍝ the result is an array (a 1-row by N-column matrix). to print out one vendor
⍝ per line, we reshape it to be N rows by 1 column instead. 
{(1⌷⍴) 1  } vendorList
Output:
 Intel Corporate      
 Apple, Inc.          
 Cisco Systems, Inc   
 PEGATRON CORPORATION 
 Dell Inc.        

AppleScript[edit]

set apiRoot to "https://api.macvendors.com"
set macList to {"88:53:2E:67:07:BE", "D4:F4:6F:C9:EF:8D", ¬
                "FC:FB:FB:01:FA:21", "4c:72:b9:56:fe:bc", "00-14-22-01-23-45"}

on lookupVendor(macAddr)
  global apiRoot
  return do shell script "curl " & apiRoot & "/" & macAddr
end lookupVendor

set table to { lookupVendor(first item of macList) }
repeat with burger in macList's items 2 thru -1
    delay 1.5
    set end of table to lookupVendor(burger)
end repeat

set text item delimiters to linefeed
return table as string

If this is part of a larger script you probably want to save and restore the text item delimiters:

set savedTID to text item delimiters
set text item delimiters to linefeed
set tableText to table as string
set text item delimiters to savedTID
return tableText
Output:
Intel Corporate
Apple, Inc.
Cisco Systems, Inc
PEGATRON CORPORATION
Dell Inc.

Arturo[edit]

loop ["FC-A1-3E" "FC:FB:FB:01:FA:21" "BC:5F:F4"] 'mac [
    print [mac "=>" read ~"http://api.macvendors.com/|mac|"]
    pause 1500
]
Output:
FC-A1-3E => Samsung Electronics Co.,Ltd 
FC:FB:FB:01:FA:21 => Cisco Systems, Inc 
BC:5F:F4 => ASRock Incorporation

AutoHotkey[edit]

macLookup(MAC){
	WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
	WebRequest.Open("GET", "http://api.macvendors.com/" MAC)
	WebRequest.Send()
	return WebRequest.ResponseText
}
Examples:
MsgBox % macLookup("00-14-22-01-23-45")
Outputs:
Dell Inc.

BaCon[edit]

This code requires BaCon 3.8.2 or higher.

OPTION TLS TRUE

website$ = "api.macvendors.com"
mac$ = "b0:52:16:d0:3c:fb"

OPEN website$ & ":443" FOR NETWORK AS mynet
    SEND "GET /" & mac$ & " HTTP/1.1\r\nHost: " & website$ & "\r\n\r\n" TO mynet
    RECEIVE info$ FROM mynet
CLOSE NETWORK mynet

PRINT TOKEN$(info$, 2, "\r\n\r\n")
Output:
Hon Hai Precision Ind. Co.,Ltd.

C[edit]

Takes MAC address as input, prints usage on incorrect invocation, requires libcurl

#include <curl/curl.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

/* Length of http://api.macvendors.com/ */
#define FIXED_LENGTH 16

struct MemoryStruct {
  char *memory;
  size_t size;
};
 
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
  size_t realsize = size * nmemb;
  struct MemoryStruct *mem = (struct MemoryStruct *)userp;
 
  mem->memory = realloc(mem->memory, mem->size + realsize + 1);
 
  memcpy(&(mem->memory[mem->size]), contents, realsize);
  mem->size += realsize;
  mem->memory[mem->size] = 0;
 
  return realsize;
}

void checkResponse(char* str){
	char ref[] = "Vendor not found";
	int len = strlen(str),flag = 1,i;
	
	if(len<16)
		fputs(str,stdout);
	else{
		for(i=0;i<len && i<16;i++)
			flag = flag && (ref[i]==str[i]);
		
		flag==1?fputs("N/A",stdout):fputs(str,stdout);
	}
}

int main(int argC,char* argV[])
{
		if(argC!=2)
			printf("Usage : %s <MAC address>",argV[0]);
		else{
			CURL *curl;
			int len = strlen(argV[1]);
			char* str = (char*)malloc((FIXED_LENGTH + len)*sizeof(char));
			struct MemoryStruct chunk;
			CURLcode res;
 
			chunk.memory = malloc(1);
			chunk.size = 0;  
 
        if ((curl = curl_easy_init()) != NULL) {
				sprintf(str,"http://api.macvendors.com/%s",argV[1]);

                                curl_easy_setopt(curl, CURLOPT_URL, str);
				curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
				curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
				
				free(str);
				
				res = curl_easy_perform(curl);
				
                if (res == CURLE_OK) {
				checkResponse(chunk.memory);
                                return EXIT_SUCCESS;
                }
				
                curl_easy_cleanup(curl);
			}
		}
        
        return EXIT_FAILURE;
}

Invocation and output :

C:\rosettaCode>macLookUp 00-11-22-33-44-55-66
CIMSYS Inc
C:\rosettaCode>macLookUp 10-11-22-33-44-55-66
N/A

C#[edit]

using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task<string> LookupMac(string MacAddress)
    {
        var uri = new Uri("http://api.macvendors.com/" + WebUtility.UrlEncode(MacAddress));
        using (var wc = new HttpClient())
            return await wc.GetStringAsync(uri);
    }
    static void Main(string[] args)
    {
        foreach (var mac in new string[] { "88:53:2E:67:07:BE", "FC:FB:FB:01:FA:21", "D4:F4:6F:C9:EF:8D" })
            Console.WriteLine(mac + "\t" + LookupMac(mac).Result);
        Console.ReadLine();
    }
}
Output:
88:53:2E:67:07:BE       Intel Corporate
FC:FB:FB:01:FA:21       Cisco Systems, Inc
D4:F4:6F:C9:EF:8D       Apple, Inc.

C++[edit]

Library: Boost
// This code is based on the example 'Simple HTTP Client' included with
// the Boost documentation.

#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <iostream>
#include <string>

bool get_mac_vendor(const std::string& mac, std::string& vendor) {
    namespace beast = boost::beast;
    namespace http = beast::http;
    namespace net = boost::asio;
    using tcp = net::ip::tcp;

    net::io_context ioc;
    tcp::resolver resolver(ioc);
    const char* host = "api.macvendors.com";

    beast::tcp_stream stream(ioc);
    stream.connect(resolver.resolve(host, "http"));

    http::request<http::string_body> req{http::verb::get, "/" + mac, 10};
    req.set(http::field::host, host);
    req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
    http::write(stream, req);

    beast::flat_buffer buffer;
    http::response<http::string_body> res;
    http::read(stream, buffer, res);

    bool success = res.result() == http::status::ok;
    if (success)
        vendor = res.body();

    beast::error_code ec;
    stream.socket().shutdown(tcp::socket::shutdown_both, ec);
    if (ec && ec != beast::errc::not_connected)
        throw beast::system_error{ec};

    return success;
}

int main(int argc, char** argv) {
    if (argc != 2 || strlen(argv[1]) == 0) {
        std::cerr << "usage: " << argv[0] << " MAC-address\n";
        return EXIT_FAILURE;
    }
    try {
        std::string vendor;
        if (get_mac_vendor(argv[1], vendor)) {
            std::cout << vendor << '\n';
            return EXIT_SUCCESS;
        } else {
            std::cout << "N/A\n";
        }
    } catch(std::exception const& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }
    return EXIT_FAILURE;
}
Output:
% ./mac_vendor_lookup 0c:4d:e9:00:00:00
Apple, Inc.

Common Lisp[edit]

(quicklisp:quickload :Drakma)            ; or load it in another way

(defun mac-vendor (mac)
  (check-type mac string "A MAC address as a string")
  (multiple-value-bind (vendor status)
    (drakma:http-request (format nil "http://api.macvendors.com/~a" mac))
    (if (= 200 status)
      (format t "~%Vendor is ~a" vendor)
      (error "~%Not a MAC address: ~a" mac))))

Delphi[edit]

Library: IdHttp
program MAC_Vendor_Lookup;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  IdHttp;

function macLookUp(mac: string): string;
begin
  Result := '';
  with TIdHTTP.Create(nil) do
  begin
    try
      Result := Get('http://api.macvendors.com/' + mac);

    except
      on E: Exception do
        Writeln(e.Message);
    end;
    Free;
  end;
end;

begin
  Writeln(macLookUp('FC-A1-3E'));
  sleep(1000);
  Writeln(macLookUp('FC:FB:FB:01:FA:21'));
  sleep(1000);
  Writeln(macLookUp('BC:5F:F4'));
  readln;
end.
Output:
Samsung Electronics Co.,Ltd
Cisco Systems, Inc
ASRock Incorporation

Factor[edit]

USING: accessors calendar continuations http.client io kernel
sequences threads ;

: mac-vendor ( str -- str )
    "http://api.macvendors.com/" prepend
    [ http-get nip ] [ nip response>> message>> ] recover ;

"FC-A1-3E"
"FC:FB:FB:01:FA:21"
"10-11-22-33-44-55-66"
[ mac-vendor print 1 seconds sleep ] tri@
Output:
Samsung Electronics Co.,Ltd
Cisco Systems, Inc
Not Found

FreeBASIC[edit]

Function pipeout(Byval s As String = "") Byref As String
    Var f = Freefile
    Dim As String tmp
    Open Pipe s For Input As #f 
    s = ""
    Do Until Eof(f)
        Line Input #f, tmp
        s &= tmp
    Loop
    Close #f
    Return s
End Function 

Function lookupvendor(webpage As String, mac As String) As String
    Return pipeout("powershell " + "(Invoke-WebRequest " + webpage + mac + ")")
End Function

Dim As String macs(1 To 4) = {"FC-A1-3E","FC:FB:FB:01:FA:21","88:53:2E:67:07:BE","D4:F4:6F:C9:EF:8D"}

For i As Integer = 1 To Ubound(macs)
    Var d = lookupvendor("api.macvendors.com/", macs(i))
    Var e = Instr(d, "RawContent")
    Print Mid(d, 66, e-66)
Next i
Sleep
Output:
Samsung Electronics Co.,Ltd
Cisco Systems, Inc
Intel Corporate
Apple, Inc.

Free Pascal[edit]

program MACVendorLookup;

uses
  fphttpclient;

var
  res: String;
begin
  if paramCount > 0 then begin

    With TFPHttpClient.Create(Nil) do
    try
      allowRedirect := true;
      try
        res := Get('http://api.macvendors.com/' + ParamStr(1));
        writeLn(res);
      except
        writeLn('N/A');
      end;
    finally
      Free;
    end;
  end;
end.
Output:
./MACVendorLookup 10-11-22-33-44-55-66
N/A

./MACVendorLookup 00-11-22-33-44-55-66
CIMSYS Inc

Go[edit]

package main

import (
	"net/http"
	"fmt"
	"io/ioutil"
)

func macLookUp(mac string) (res string){
	resp, _ := http.Get("http://api.macvendors.com/" + mac)
	body, _ := ioutil.ReadAll(resp.Body)
	res = string(body)
	return
}

func main()  {
	fmt.Println(macLookUp("FC-A1-3E"))
	fmt.Println(macLookUp("FC:FB:FB:01:FA:21"))
	fmt.Println(macLookUp("BC:5F:F4"))
}
Output:
Samsung Electronics Co.,Ltd
Cisco Systems, Inc
ASRock Incorporation

Haskell[edit]

Works with: GHC version 8.0.2
Library: http-client
#!/usr/bin/env stack
{- stack
  script
  --resolver lts-9.0
  --package bytestring
  --package http-client
  --package http-types
-}

{-# LANGUAGE MultiWayIf #-}

import Control.Exception (try)
import Control.Monad (forM_)
import qualified Data.ByteString.Lazy.Char8 as L8 (ByteString, unpack)
import Network.HTTP.Client
  (Manager, parseRequest, httpLbs, responseStatus, responseBody,
   newManager, defaultManagerSettings, Response, HttpException)
import Network.HTTP.Types.Status (statusIsSuccessful, notFound404)
import System.Environment (getArgs)
import Text.Printf (printf)

fetchURL :: Manager
         -> String
         -> IO (Either HttpException (Response L8.ByteString))
fetchURL mgr url = try $ do
  req <- parseRequest url
  httpLbs req mgr

lookupMac :: Manager -> String -> IO String
lookupMac mgr mac = do
  eth <- fetchURL mgr $ "http://api.macvendors.com/" ++ mac
  return $ case eth of
             Left _ -> "null"
             Right resp -> let body = responseBody resp
                               status = responseStatus resp
                           in if | status == notFound404 -> "N/A"
                                 | not (statusIsSuccessful status) -> "null"
                                 | otherwise -> L8.unpack body

main :: IO ()
main = do
  args <- getArgs
  mgr <- newManager defaultManagerSettings
  forM_ args $ \mac -> do
    putStr $ printf "%-17s" mac ++ " = "
    vendor <- lookupMac mgr mac
    putStrLn vendor
Output:
$ ./RosettaMac.hs 00:15:ed:f0:00:00 ff:ff:ff:ff:ff:ff 88:53:2E:67:07:BE FC:FB:FB:01:FA:21 D4:F4:6F:C9:EF:8D banana
00:15:ed:f0:00:00 = Fulcrum Microsystems, Inc.
ff:ff:ff:ff:ff:ff = N/A
88:53:2E:67:07:BE = Intel Corporate
FC:FB:FB:01:FA:21 = Cisco Systems, Inc
D4:F4:6F:C9:EF:8D = Apple, Inc.
banana            = N/A

J[edit]

Solution

require 'web/gethttp'
lookupMACvendor=: [: gethttp 'http://api.macvendors.com/'&,

Example Usage

   addr=: '88:53:2E:67:07:BE';'FC:FB:FB:01:FA:21';'D4:F4:6F:C9:EF:8D';'23:45:67'
   (,&'   ' , lookupMACvendor)&> addr
88:53:2E:67:07:BE   Intel Corporate   
FC:FB:FB:01:FA:21   Cisco Systems, Inc
D4:F4:6F:C9:EF:8D   Apple, Inc.       
23:45:67   Vendor not found

Java[edit]

package com.jamesdonnell.MACVendor;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/** MAC Vendor Lookup class.
 * www.JamesDonnell.com
 * @author James A. Donnell Jr. */
public class Lookup {
	/** Base URL for API. The API from www.macvendors.com was chosen. */
	private static final String baseURL = "http://api.macvendors.com/";

	/** Performs lookup on MAC address(es) supplied in arguments.
	 * @param args MAC address(es) to lookup. */
	public static void main(String[] args) {
		for (String arguments : args)
			System.out.println(arguments + ": " + get(arguments));
	}

	/** Performs lookup on supplied MAC address.
	 * @param macAddress MAC address to lookup.
	 * @return Manufacturer of MAC address. */
	private static String get(String macAddress) {
		try {
			StringBuilder result = new StringBuilder();
			URL url = new URL(baseURL + macAddress);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("GET");
			BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			String line;
			while ((line = rd.readLine()) != null) {
				result.append(line);
			}
			rd.close();
			return result.toString();
		} catch (FileNotFoundException e) {
			// MAC not found
			return "N/A";
		} catch (IOException e) {
			// Error during lookup, either network or API.
			return null;
		}
	}
}

JavaScript[edit]

var mac = "88:53:2E:67:07:BE";
function findmac(){
	window.open("http://api.macvendors.com/" + mac);
}

findmac();
Output:
Intel Corporate

Julia[edit]

# v0.6.0

using Requests

function getvendor(addr::String)
    try
        get("http://api.macvendors.com/$addr") |> readstring
    catch e
        nothing
    end
end

for addr in ["88:53:2E:67:07:BE", "FC:FB:FB:01:FA:21", "D4:F4:6F:C9:EF:8D", "23:45:67"]
    println("$addr -> ", getvendor(addr))
end
Output:
88:53:2E:67:07:BE -> Intel Corporate
FC:FB:FB:01:FA:21 -> Cisco Systems, Inc
D4:F4:6F:C9:EF:8D -> Apple, Inc.
23:45:67 -> Vendor not found

Kotlin[edit]

// version 1.1.2

import java.net.URL

fun lookupVendor(mac: String) = URL("http://api.macvendors.com/" + mac).readText()

fun main(args: Array<String>) {
    val macs = arrayOf("FC-A1-3E", "FC:FB:FB:01:FA:21", "88:53:2E:67:07:BE", "D4:F4:6F:C9:EF:8D")
    for (mac in macs) println(lookupVendor(mac))
}
Output:
Samsung Electronics Co.,Ltd
Cisco Systems, Inc
Intel Corporate
Apple, Inc.

[edit]

Works with: UCB Logo
make "api_root "http://api.macvendors.com/
make "mac_list [88:53:2E:67:07:BE D4:F4:6F:C9:EF:8D FC:FB:FB:01:FA:21
                4c:72:b9:56:fe:bc 00-14-22-01-23-45]

to lookup_vendor :mac
  output first shell (sentence [curl -s] (word :api_root :mac) [&& echo])
end

print lookup_vendor first :mac_list
foreach butfirst :mac_list [
  wait 90
  print lookup_vendor ?
]
bye
bye
Output:
Intel Corporate
Apple, Inc.
Cisco Systems, Inc
PEGATRON CORPORATION
Dell Inc.

Lua[edit]

-- Requires LuaSocket extension by Lua
-- Created by James A. Donnell Jr.
-- www.JamesDonnell.com

local baseURL = "http://api.macvendors.com/"

local function lookup(macAddress)
	http = require "socket.http"
	result, statuscode, content = http.request(baseURL .. macAddress)
	return result
end

local macAddress = "FC-A1-3E-2A-1C-33"
print(lookup(macAddress))

M2000 Interpreter[edit]

Module Checkit {
      httpGet$=lambda$  (url$, timeout=500)->{
            declare htmldoc "WinHttp.WinHttpRequest.5.1"
            Method htmldoc "SetTimeouts", timeout, timeout, timeout, timeout
            Method htmldoc "open","GET", url$, false
            Method htmldoc "setRequestHeader","Content-Type", "application/x-www-form-urlencoded"
            Method htmldoc "send"
            With  htmldoc, "responseText" as ready$ 
            res$=trim$(ready$)
            if left$(res$,1)="{" then 
                  ="N/A"
            else
                   =res$
            end if
            declare htmldoc nothing
      }
       Urls=("88:53:2E:67:07:BE", "FC:FB:FB:01:FA:21", "D4:F4:6F:C9:EF:8D", "23:45:67")
       url=each(URLs)
       While Url {
             Print Array$(URL), httpGet$("http://api.macvendors.com/"+Array$(URL))
             Wait 20
      }
}
Checkit

Mathematica/Wolfram Language[edit]

macLookup[mac_String] := Quiet[Check[Import["http://api.macvendors.com/" <> mac], "N/A"]]
Examples:
macLookup["00-14-22-01-23-45"]
Outputs:
Dell Inc.

Nim[edit]

import httpclient

for mac in ["FC-A1-3E", "FC:FB:FB:01:FA:21", "BC:5F:F4"]:
  echo newHttpClient().getContent("http://api.macvendors.com/"&mac)
Output:
Samsung Electronics Co.,Ltd
Cisco Systems, Inc
ASRock Incorporation

OCaml[edit]

(* build with ocamlfind ocamlopt -package netclient -linkpkg macaddr.ml -o macaddr *)

open Printf
open Nethttp_client.Convenience
open Unix

(* example vendors, including a nonsense one *)

let vendors = ["FF:FF:FF:67:07:BE"; "D4:F4:6F:C9:EF:8D"; "FC:FB:FB:01:FA:21"; "88:53:2E:67:07:BE"]

let get_vendor addr =
  sleep 3; (* built-in delay to handle rate-limiting at macvendors.com *)
  
  let client = http_get_message ("http://api.macvendors.com/" ^ addr) in
  match client # response_status_code with
  | 200 -> client # response_body # value
  | 404 -> "N/A"
  | _ -> "NULL"
             
let rec parse_vendors vendors =
  match vendors with
  | [] -> []
  | hd::tl -> get_vendor hd :: parse_vendors tl

let rec print_vendors vendor_list =
  match vendor_list with
  | [] -> ""
  | hd::tl -> printf "%s\n" hd; print_vendors tl
  
let main =
  let vendor_list = parse_vendors vendors in
  print_vendors vendor_list
Output:
N/A
Apple, Inc.
Cisco Systems, Inc
Intel Corporate


Perl[edit]

#!/usr/bin/env perl -T
use v5.18.2;
use warnings;
use LWP;
use Time::HiRes qw(sleep);

our $VERSION = 1.000_000;

my $ua = LWP::UserAgent->new;

no warnings 'qw';
my @macs = qw(
    FC-A1-3EFC:FB:FB:01:FA:21 00,0d,4b
    Rhubarb                   00-14-22-01-23-45
    10:dd:b1                  D4:F4:6F:C9:EF:8D
    FC-A1-3E                  88:53:2E:67:07:BE
    23:45:67                  FC:FB:FB:01:FA:21
    BC:5F:F4
);

while (my $mac = shift @macs) {
    my $vendor = get_mac_vendor($mac);
    if ($vendor) {
        say "$mac = $vendor";
    }
    sleep 1.5 if @macs;
}

sub get_mac_vendor {
    my $s = shift;

    my $req = HTTP::Request->new( GET => "http://api.macvendors.com/$s" );
    my $res = $ua->request($req);

    # A error related to the network connectivity or the API should
    # return a null result.
    if ( $res->is_error ) {
        return;
    }

    # A MAC address that does not return a valid result should
    # return the String "N/A".
    if (  !$res->content
        or $res->content eq 'Vendor not found' )
    {
        return 'N/A';
    }

    return $res->content;
}

# IEEE 802:
#  Six groups of two hexadecimal digits separated by hyphens or colons,
#    like 01-23-45-67-89-ab or 01:23:45:67:89:ab
#  Three groups of four hexadecimal digits separated by dots (.),
#    like 0123.4567.89ab
#sub validmac {
#    my $s = shift;
#
#    my $hex    = qr{ [A-Fa-f[:digit:]] }xms;
#    my $hex2ws = qr{ [-:] $hex{2} }xms;
#
#    if (   $s =~ m{\A $hex{2} $hex2ws{5} \z}xms
#        or $s =~ m{\A $hex{4} [.] $hex{4}  [.] $hex{4} \z}xms )
#    {
#        return 'true';
#    }
#    return;
#}
Output:
FC-A1-3EFC:FB:FB:01:FA:21 = Samsung Electronics Co.,Ltd
00,0d,4b = Roku, Inc.
00-14-22-01-23-45 = Dell Inc.
10:dd:b1 = Apple, Inc.
D4:F4:6F:C9:EF:8D = Apple, Inc.
FC-A1-3E = Samsung Electronics Co.,Ltd
88:53:2E:67:07:BE = Intel Corporate
FC:FB:FB:01:FA:21 = Cisco Systems, Inc
BC:5F:F4 = ASRock Incorporation

Phix[edit]

Library: Phix/libcurl
without js -- libcurl
string test = "00-11-22-33-44-55-66"     -- CIMSYS Inc
--string test = "10-11-22-33-44-55-66"      -- N/A
include builtins/libcurl.e
curl_global_init()
atom curl = curl_easy_init()
string url = sprintf("http://api.macvendors.com/%s",{test})
curl_easy_setopt(curl, CURLOPT_URL, url)
object res = curl_easy_perform_ex(curl)
if string(res) then
    if res="Vendor not found"
    or res=`{"errors":{"detail":"Not Found"}}` then
        res = "N/A"
    end if
    ?res
else
    ?{"error",res}
end if
curl_easy_cleanup(curl)
curl_global_cleanup()
Output:
CIMSYS Inc

PHP[edit]

Translation of: AppleScript
<?php
$apiRoot = "https://api.macvendors.com";
$macList = array("88:53:2E:67:07:BE", "D4:F4:6F:C9:EF:8D", 
		 "FC:FB:FB:01:FA:21", "4c:72:b9:56:fe:bc", "00-14-22-01-23-45");

$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
foreach ($macList as $burger) {
  curl_setopt($curl, CURLOPT_URL, "$apiRoot/$burger");
  echo(curl_exec($curl));
  echo("\n");
  sleep(2);
}
curl_close($curl);
?>
Output:
Intel Corporate
Apple, Inc.
Cisco Systems, Inc
PEGATRON CORPORATION
Dell Inc.

PowerShell[edit]

Translation of: AppleScript
$apiRoot = "http://api.macvendors.com"
$macAddresses = @("88:53:2E:67:07:BE", "D4:F4:6F:C9:EF:8D",
                  "FC:FB:FB:01:FA:21", "4c:72:b9:56:fe:bc",
                  "00-14-22-01-23-45")

$macAddresses | % {
  (Invoke-WebRequest "$apiRoot/$_").Content
  Start-Sleep 1.5
}
Output:
Intel Corporate
Apple, Inc.
Cisco Systems, Inc
PEGATRON CORPORATION
Dell Inc.

Python[edit]

Library: requests
import requests

for addr in ['88:53:2E:67:07:BE', 'FC:FB:FB:01:FA:21',
        'D4:F4:6F:C9:EF:8D', '23:45:67']:
    vendor = requests.get('http://api.macvendors.com/' + addr).text
    print(addr, vendor)
Output:
88:53:2E:67:07:BE Intel Corporate
FC:FB:FB:01:FA:21 Cisco Systems, Inc
D4:F4:6F:C9:EF:8D Apple, Inc.
23:45:67 Vendor not found

Racket[edit]

#lang racket

(require net/url)

(define (lookup-MAC-address addr)
  (port->string
   (get-pure-port
    (url "http" #f "api.macvendors.com" #f #t (list (path/param addr null)) null #f))))

(module+ test
(for ((i (in-list '("88:53:2E:67:07:BE"
                    "FC:FB:FB:01:FA:21"
                    "D4:F4:6F:C9:EF:8D"))))
  (printf "~a\t~a~%" i (lookup-MAC-address i))))
Output:
88:53:2E:67:07:BE	Intel Corporate
FC:FB:FB:01:FA:21	Cisco Systems, Inc
D4:F4:6F:C9:EF:8D	Apple, Inc.

Raku[edit]

(formerly Perl 6)

Works with: Rakudo version 2018.03

Apparently there is some rate limiting on place now, sleep a bit between requests.

use HTTP::UserAgent;
 
my $ua = HTTP::UserAgent.new;
 
$ua.timeout = 10; # seconds
 
my $server = 'http://api.macvendors.com/';
 
sub lookup ($mac) {
    my $response = $ua.get: "$server+$mac";
    sleep 1;
    return $response.is-success ?? $response.content !! 'N/A';
 
    CATCH {             # Normally you would report some information about what
        default { Nil } # went wrong, but the task specifies to ignore errors.
    }
}
 
for <
BC:5F:F4
FC-A1-3E
10:dd:b1
00:0d:4b
23:45:67
> -> $mac { say lookup $mac }
Output:
ASRock Incorporation
Samsung Electronics Co.,Ltd
Apple, Inc.
Roku, Inc.
N/A

Red[edit]

print read rejoin [http://api.macvendors.com/ ask "MAC address: "]
Output:
MAC address: 88:53:2E:67:07:BE
Intel Corporate

REXX[edit]

This REXX version only works under Microsoft Windows and Regina REXX.

/*REXX pgm shows a network device's manufacturer based on the Media Access Control addr.*/
win_command         = 'getmac'                   /*name of the Microsoft Windows command*/
win_command_options = '/v /fo list'              /*options  of     "        "       "   */
?3= 'Network Adapter:'                           /*search keywords for Network Adapter. */
?4= 'Physical Address:'                          /*   "       "     "  Physical Address.*/
upper ?3 ?4                                      /*uppercase in case for capitol letters*/
@.=;            @.0= 0                           /*just─in─case values for the keywords.*/
rc= 0                                            /*  "   "   "  value for the returnCode*/
address system win_command win_command_options   with   output stem @.  /*issue command.*/
if rc\==0  then do                               /*display an error if not successful.  */
                say
                say '***error*** from command: '     win_command     win_command_options
                say 'Return code was: '    rc
                say
                exit rc
                end
MACaddr=.                                        /*just─in─case value for the keyword.  */
maker=.                                          /*  "   "   "    "    "   "     "      */
           do j=1  for @.0;  $= @.j;  upper $    /*parse each of the possible responses.*/
           if left($, length(?3))=?3  then maker=   subword(@.j, 3)   /*is this the one?*/
           if left($, length(?4))=?4  then MACaddr= word(@.j, 3)      /* "   "   "   "  */
           end   /*k*/
                                                 /* [↑]  Now, display good or bad stuff.*/
if maker=. | MACaddr==.  then say 'MAC address manufacturer not found.'
                         else say 'manufacturer for MAC address  '  MACaddr "  is  " maker
exit 0                                           /*stick a fork in it,  we're all done. */
output   when using the default input:
manufacturer for MAC address   00-16-17-F9-C8-AA    is    Broadcom NetLink (TM) Gigabit Ethernet

Ring[edit]

# Project: MAC Vendor Lookup

load "stdlib.ring"
macs = ["FC-A1-3E","FC:FB:FB:01:FA:21","88:53:2E:67:07:BE","D4:F4:6F:C9:EF:8D"]
for mac = 1 to len(macs)
     lookupvendor(macs[mac])
next

func lookupvendor(mac)
       url = download("api.macvendors.com/" + mac)
       see url + nl

Output:

Samsung Electronics Co.,Ltd
Cisco Systems, Inc
Intel Corporate
Apple, Inc.

Ruby[edit]

require 'net/http'

arr = ['88:53:2E:67:07:BE', 'FC:FB:FB:01:FA:21', 'D4:F4:6F:C9:EF:8D', '23:45:67']

arr.each do |addr|
  vendor = Net::HTTP.get('api.macvendors.com', "/#{addr}/") rescue nil
  puts "#{addr}  #{vendor}" 
end
Output:
88:53:2E:67:07:BE  Intel Corporate
FC:FB:FB:01:FA:21  Cisco Systems, Inc
D4:F4:6F:C9:EF:8D  Apple, Inc.
23:45:67  Vendor not found

Rust[edit]

extern crate reqwest;

use std::{thread, time};

fn get_vendor(mac: &str) -> Option<String> {
    let mut url = String::from("http://api.macvendors.com/");
    url.push_str(mac);
    let url_ref = &url;
    match reqwest::get(url_ref) {
        Ok(mut res) => match res.text() {
            Ok(text) => {
                if text.contains("Not Found") {
                    Some("N/A".to_string())
                } else {
                    Some(text)
                }
            }
            Err(e) => {
                println!("{:?}", e);
                None
            }
        },
        Err(e) => {
            println!("{:?}", e);
            None
        }
    }
}

fn main() {
    let duration = time::Duration::from_millis(1000);
    match get_vendor("88:53:2E:67:07:BE") {
        None => println!("Error!"),
        Some(text) => println!("{}", text),
    }
    thread::sleep(duration);
    match get_vendor("FC:FB:FB:01:FA:21") {
        None => println!("Error!"),
        Some(text) => println!("{}", text),
    }
    thread::sleep(duration);
    match get_vendor("FC-A1-3E") {
        None => println!("Error!"),
        Some(text) => println!("{}", text),
    }
    thread::sleep(duration);
    match get_vendor("abcdefg") {
        None => println!("Error!"),
        Some(text) => println!("{}", text),
    }
}

Output:

Intel Corporate
Cisco Systems, Inc
Samsung Electronics Co.,Ltd
N/A

Scala[edit]

object LookUp extends App {
  val macs = Seq("FC-A1-3E", "FC:FB:FB:01:FA:21", "88:53:2E:67:07:BE", "D4:F4:6F:C9:EF:8D")

  def lookupVendor(mac: String) =
    scala.io.Source.fromURL("""http://api.macvendors.com/""" + mac, "UTF-8").mkString

  macs.foreach(mac => println(lookupVendor(mac)))
}

Scheme[edit]

Translation of: Applescript
Works with: Chicken Scheme
Library: http-client
(import http-client (chicken io))
(define api-root "http://api.macvendors.com")
(define mac-addresses '("88:53:2E:67:07:BE" "D4:F4:6F:C9:EF:8D"
                        "FC:FB:FB:01:FA:21" "4c:72:b9:56:fe:bc"
                        "00-14-22-01-23-45"))

(define get-vendor (lambda (mac-address)
  (with-input-from-request (string-append api-root "/" mac-address)
      #f read-string)))

(display (get-vendor (car mac-addresses)))
(newline)
(map (lambda (burger) (sleep 2) (display (get-vendor burger)) (newline))
     (cdr mac-addresses))
Output:
Intel Corporate
Apple, Inc.
Cisco Systems, Inc
PEGATRON CORPORATION
Dell Inc.

Tcl[edit]

package require http

# finally is a bit like go's defer
proc finally args {
    tailcall trace add variable :#finally#: unset [list apply [list args $args]]
}

# basic wrapper for http::geturl
proc geturl {url} {
    set tok [::http::geturl $url]
    finally ::http::cleanup $tok
    ::http::data $tok
}   
proc maclookup {mac} {
    geturl http://api.macvendors.com/$mac
}

foreach mac {00-14-22-01-23-45 88:53:2E:67:07:BE} {
    puts "$mac\t[maclookup $mac]"
}
Output:
00-14-22-01-23-45       Dell Inc.
88:53:2E:67:07:BE       Intel Corporate

UNIX Shell[edit]

Translation of: AppleScript
Works with: Bourne Again SHell
Works with: Korn Shell version 93+
Works with: Z Shell

Surprising that nobody had implemented the Bash / Shell version yet.

macList=(88:53:2E:67:07:BE D4:F4:6F:C9:EF:8D FC:FB:FB:01:FA:21
         4c:72:b9:56:fe:bc 00-14-22-01-23-45)

lookup() {
  curl -s "http://api.macvendors.com/$1" && echo
}

lookup "${macList[0${ZSH_VERSION:++1}]}"
for burger in "${macList[@]:1}"; do
  sleep 2
  lookup "$burger"
done

It can be made to work in a pure-POSIX shell without array variables:

Works with: Bourne Shell
Works with: Almquist Shell
set -- 88:53:2E:67:07:BE D4:F4:6F:C9:EF:8D FC:FB:FB:01:FA:21 \
       4c:72:b9:56:fe:bc 00-14-22-01-23-45

lookup() {
  curl -s "http://api.macvendors.com/$1" && echo
}

lookup "$1"
shift
for burger; do
  sleep 2
  curl -s "http://api.macvendors.com/$burger" && echo
done

And hey, just for completeness, let's toss in a [t]csh version:

Works with: C Shell
set macList=(88:53:2E:67:07:BE D4:F4:6F:C9:EF:8D FC:FB:FB:01:FA:21 \
             4c:72:b9:56:fe:bc 00-14-22-01-23-45)

alias lookup curl -s "http://api.macvendors.com/!":1 "&&" echo

lookup "$macList[1]"
foreach burger ($macList[2-]:q)
  sleep 2
  lookup "$burger"
end
Output:

All the above versions have identical output:

Intel Corporate
Apple, Inc.
Cisco Systems, Inc
PEGATRON CORPORATION
Dell Inc.

VBScript[edit]

a=array("00-20-6b-ba-d0-cb","00-40-ae-04-87-86")
set WebRequest = CreateObject("WinHttp.WinHttpRequest.5.1")

for each MAC in a 
  if b<>0 then   wscript.echo "Spacing next request...": wscript.sleep 2000
  WebRequest.Open "GET", "http://api.macvendors.com/"& mac,1
  WebRequest.Send()
  WebRequest.WaitForResponse 
  b=b+1
  wscript.echo mac & " -> " & WebRequest.ResponseText
next

Output:

00-20-6b-ba-d0-cb -> KONICA MINOLTA HOLDINGS, INC.
Spacing next request...
00-40-ae-04-87-86 -> DELTA CONTROLS, INC.

Vlang[edit]

import net.http
import time

const macs = 
('
FC-A1-3E
FC:FB:FB:01:FA:21
D4:F4:6F:C9:EF:8D
')

fn main() {
    for line in macs.split('\n') {
        if line !='' {
            println(mac_lookup(line))
            time.sleep(2 * time.second) // considerate delay between attempts
        }
    }
}

fn mac_lookup(mac string) string {
    resp := http.get("http://api.macvendors.com/" + mac) or {println('No data from server') return ''}
    return resp.body.str()
}
Output:
Samsung Electronics Co.,Ltd
Cisco Systems, Inc
Apple, Inc.

Wren[edit]

Wren CLI doesn't currently expose a way to look up a MAC address.

However, if Wren is embedded in (say) a suitable Go program, then we can ask the latter to do it for us.

/* mac_vendor_lookup.wren */
class MAC {
    foreign static lookup(address)
}

System.print(MAC.lookup("FC:FB:FB:01:FA:21"))
for (i in 1..1e8) {} // slow down request
System.print(MAC.lookup("23:45:67"))

which we embed in the following Go program and run it.

Library: WrenGo
/* mac_vendor_lookup.go */
package main

import (
    wren "github.com/crazyinfin8/WrenGo"
    "io/ioutil"
    "net/http"
)

type any = interface{}

func macLookup(vm *wren.VM, parameters []any) (any, error) {
    mac := parameters[1].(string)
    resp, err := http.Get("http://api.macvendors.com/" + mac)
    if err != nil {
        return nil, nil
    }
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, nil
    }
    var vendor = string(body)
    if vendor == `{"errors":{"detail":"Not Found"}}` {
        return "N/A", nil
    }
    return vendor, nil
}    

func main() {
    vm := wren.NewVM()
    fileName := "mac_vendor_lookup.wren"
    methodMap := wren.MethodMap{"static lookup(_)": macLookup}
    classMap := wren.ClassMap{"MAC": wren.NewClass(nil, nil, methodMap)}
    module := wren.NewModule(classMap)
    vm.SetModule(fileName, module)
    vm.InterpretFile(fileName)
    vm.Free()
}
Output:
Cisco Systems, Inc
N/A

zkl[edit]

Translation of: Lua

Uses libcurl (the multiprotocol file transfer library) to do the web query

var [const] CURL=Import("zklCurl");   // libcurl
const MAC_VENDORS="http://api.macvendors.com/";

fcn lookUp(macAddress){
   httpAddr:=MAC_VENDORS + macAddress;
   vender:=CURL().get(httpAddr); //-->(Data,bytes of header,bytes of trailer)
   vender=vender[0].del(0,vender[1]);  // remove HTTP header
   vender.text;		// Data --> String (Data is a byte bucket)
}
lookUp("FC-A1-3E-2A-1C-33").println();
lookUp("4c:72:b9:56:fe:bc").println();
lookUp("foobar").println();
Output:
Samsung Electronics Co.,Ltd
PEGATRON CORPORATION
Vendor not found

Zoea[edit]

program: mac_vendor_lookup

data: 'http://api.macvendors.com/'

input: 'D4:F4:6F:C9:EF:8D'
derive: 'http://api.macvendors.com/D4:F4:6F:C9:EF:8D'
output: 'Apple, Inc.'

Zoea Visual[edit]

MAC Vendor Lookup