MAC Address Lookup Tool
Lookup MAC Address
Powered by macvendors.com API. Auto-formats to XX:XX:XX:XX:XX:XX
MAC Address
Manufacturer / Vendor
Lookup History
Your lookup history will appear here.
Your lookup history will appear here.
'; return; } ui.logList.innerHTML = lookupLog.map(log => `
${log.timestamp}
`).join('');
}
function logEntry(mac, vendor) {
const timestamp = new Date().toLocaleString('en-US');
lookupLog.unshift({ timestamp, mac, vendor });
if (lookupLog.length > 50) lookupLog.pop(); // Limit log size
saveState();
renderLog();
}
function renderResults() {
ui.summaryMac.textContent = currentResult.mac;
ui.summaryVendor.textContent = currentResult.vendor;
ui.resultsContainer.style.display = 'block';
}
function showMessage(message, isError = true) {
ui.errorMsg.textContent = message;
ui.errorMsg.style.display = 'block';
}
// --- API LOGIC ---
async function fetchMacVendor(mac) {
ui.loader.style.display = 'block';
ui.resultsContainer.style.display = 'none';
ui.errorMsg.style.display = 'none';
currentResult = { mac: mac, vendor: '' };
if (!MAC_REGEX.test(mac)) {
showMessage('Invalid MAC Address format. Please use XX:XX:XX:XX:XX:XX');
ui.loader.style.display = 'none';
return;
}
try {
// Using macvendors.com's free, CORS-enabled API
const response = await fetch(`https://api.macvendors.com/${encodeURIComponent(mac)}`);
if (response.status === 404) {
throw new Error("Vendor not found for this MAC address.");
}
if (!response.ok) {
throw new Error(`API request failed with status ${response.status}`);
}
const vendor = await response.text();
currentResult.vendor = vendor;
renderResults();
logEntry(mac, vendor);
} catch (error) {
console.error("MAC Fetch Error:", error);
showMessage(error.message);
logEntry(mac, `Error: ${error.message}`);
} finally {
ui.loader.style.display = 'none';
}
}
// --- PDF LOGIC ---
function downloadPDF(type) {
const { jsPDF } = window.jspdf;
if (!jsPDF || !window.jspdf.autoTable) { alert("PDF library not loaded!"); return; }
const doc = new jsPDF();
if (type === 'current') {
if (!currentResult.mac) {
alert("Please run a lookup before downloading.");
return;
}
doc.setFontSize(18);
doc.text(`MAC Address Report: ${currentResult.mac}`, 14, 22);
doc.autoTable({
startY: 30,
theme: 'grid',
body: [
['MAC Address', currentResult.mac],
['Vendor', currentResult.vendor],
]
});
doc.save(`MAC_Report_${currentResult.mac.replace(/:/g, '')}.pdf`);
} else if (type === 'log') {
if (lookupLog.length === 0) {
alert("Log is empty. Please perform a lookup first.");
return;
}
doc.setFontSize(18);
doc.text("MAC Address Lookup Log", 14, 22);
doc.autoTable({
startY: 30,
head: [['Timestamp', 'MAC Address', 'Vendor']],
body: lookupLog.map(log => [log.timestamp, log.mac, log.vendor]),
theme: 'striped',
headStyles: { fillColor: [74, 85, 104] } // var(--primary-color)
});
doc.save("MAC_Address_Log.pdf");
}
}
// --- EVENT LISTENERS ---
ui.form.addEventListener('submit', e => {
e.preventDefault();
const mac = ui.input.value.trim();
if (mac) {
fetchMacVendor(mac);
}
});
// Auto-formatter for MAC address input
ui.input.addEventListener('input', e => {
let val = e.target.value.replace(/[^0-9a-fA-F]/g, '');
if (val.length > 12) val = val.substring(0, 12);
let formattedVal = val.match(/.{1,2}/g)?.join(':') || '';
e.target.value = formattedVal;
});
ui.downloadReportBtn.addEventListener('click', () => downloadPDF('current'));
ui.downloadLogBtn.addEventListener('click', () => downloadPDF('log'));
ui.clearLogBtn.addEventListener('click', () => {
lookupLog = [];
saveState();
renderLog();
});
// --- TABBING LOGIC ---
function switchTab(targetTabId) {
ui.tabContents.forEach(c => c.classList.remove('active'));
ui.tabButtons.forEach(b => b.classList.remove('active'));
document.getElementById(`mac-tab-${targetTabId}`).classList.add('active');
document.querySelector(`.mac-tab-button[data-tab="${targetTabId}"]`).classList.add('active');
}
function navigateTabs(dir) {
const tabs = Array.from(ui.tabButtons);
const active = tabs.find(t => t.classList.contains('active'));
let index = tabs.indexOf(active) + dir;
if (index < 0) index = 0; if (index >= tabs.length) index = tabs.length - 1;
switchTab(tabs[index].dataset.tab);
}
ui.tabButtons.forEach(button => button.addEventListener('click', () => switchTab(button.dataset.tab)));
ui.nextTabBtn.addEventListener('click', () => navigateTabs(1));
ui.prevTabBtn.addEventListener('click', () => navigateTabs(-1));
// --- UTILITY ---
function escapeHTML(str) { const p = document.createElement('p'); p.textContent = str; return p.innerHTML; }
// --- INITIALIZATION ---
loadState();
renderLog();
});
${escapeHTML(log.mac)}: ${escapeHTML(log.vendor)}
