cheat sheet

arp

Display, add, and delete entries in the Windows ARP (Address Resolution Protocol) cache — map IP addresses to MAC addresses, detect IP conflicts, and diagnose Layer 2 connectivity issues.

arp — ARP Cache Viewer and Editor

What it is

arp is a built-in Windows command that displays and manipulates the ARP (Address Resolution Protocol) cache — the table that maps IPv4 addresses to MAC addresses on the local network segment. When a host sends a packet to an IP on the same subnet, it first checks the ARP cache; if the mapping is unknown, it broadcasts an ARP request. Use arp -a to see resolved mappings, arp -s to add a static entry (useful for preventing ARP spoofing against a critical host), and arp -d to flush stale entries. The PowerShell equivalent is Get-NetNeighbor.

Availability

arp ships as C:\Windows\System32\arp.exe on all Windows versions.

cmd
arp /?

Output:

css
Displays and modifies the IP-to-Physical address translation tables used by
address resolution protocol (ARP).

ARP -s inet_addr eth_addr [if_addr]
ARP -d inet_addr [if_addr]
ARP -a [inet_addr] [-N if_addr] [-v]

  -a            Displays current ARP entries by interrogating the current
                protocol data.  If inet_addr is specified, the IP and Physical
                addresses for only the specified computer are displayed.
  -v            Displays current ARP entries in verbose mode.
  -N if_addr    Displays the ARP entries for the network interface specified
                by if_addr.
  -d inet_addr  Deletes the host specified by inet_addr.
  -s inet_addr  Adds a permanent static entry to the ARP cache.
  eth_addr      Specifies a physical address.
  if_addr       Specifies the internet address of the interface whose address
                translation table should be modified.

Syntax

cmd
arp -a [inet_addr] [-N if_addr] [-v]
arp -s inet_addr eth_addr [if_addr]
arp -d inet_addr [if_addr]

Output: (ARP table or operation result)

Essential options

SwitchMeaning
-aDisplay all ARP cache entries for all interfaces
-gAlias for -a — identical behaviour, retained from BSD-style arp tooling
-a <ip>Display the ARP entry for a specific IP address
-N <if_addr>Limit display to entries for the interface with this IP
-vVerbose — include skipped entries (e.g. loopback)
-s <ip> <mac>Add a static ARP entry
-s <ip> <mac> <if_addr>Add a static entry on a specific interface
-d <ip>Delete the ARP entry for an IP
-d *Delete all ARP cache entries (requires Administrator)

Displaying the ARP cache

arp -a shows the current ARP table for all network interfaces. Each entry shows the IP address, the corresponding MAC address, and whether the entry is dynamic (learned by ARP) or static (manually added).

cmd
arp -a

Output:

sql
Interface: 192.168.1.100 --- 0x4
  Internet Address      Physical Address      Type
  192.168.1.1           00-14-22-01-23-45     dynamic
  192.168.1.10          00-50-56-ab-cd-ef     dynamic
  192.168.1.255         ff-ff-ff-ff-ff-ff     static
  224.0.0.22            01-00-5e-00-00-16     static
  255.255.255.255       ff-ff-ff-ff-ff-ff     static

Looking up a specific IP

cmd
arp -a 192.168.1.1

Output:

sql
Interface: 192.168.1.100 --- 0x4
  Internet Address      Physical Address      Type
  192.168.1.1           00-14-22-01-23-45     dynamic

Viewing by interface

When a machine has multiple network interfaces (e.g. Ethernet + Wi-Fi), -N filters the ARP table to entries learned on the interface with the given IP address.

cmd
arp -a -N 192.168.1.100

Output:

sql
Interface: 192.168.1.100 --- 0x4
  Internet Address      Physical Address      Type
  192.168.1.1           00-14-22-01-23-45     dynamic
  192.168.1.10          00-50-56-ab-cd-ef     dynamic

Adding a static entry

A static ARP entry bypasses the dynamic resolution process for the target IP — the OS always uses the specified MAC without sending an ARP broadcast. Use this to harden the gateway mapping and prevent ARP spoofing attacks against a critical address.

cmd
arp -s 192.168.1.1 00-14-22-01-23-45

Output:

csharp
(none — exits 0 on success)

Verify the entry is now static:

cmd
arp -a 192.168.1.1

Output:

sql
Interface: 192.168.1.100 --- 0x4
  Internet Address      Physical Address      Type
  192.168.1.1           00-14-22-01-23-45     static

Deleting an entry

-d removes a single dynamic entry from the cache, forcing a fresh ARP resolution the next time the address is contacted. Use * to flush all entries (requires Administrator on Vista+).

cmd
arp -d 192.168.1.10

Output:

csharp
(none — exits 0 on success)
cmd
rem Flush all ARP cache entries
arp -d *

Output:

csharp
(none — exits 0 on success)

Detecting IP conflicts

ARP is the primary tool for diagnosing duplicate IP address conflicts on a LAN. If two machines claim the same IP, arp -a may show the MAC flipping between two values, or ping followed by arp -a will reveal the MAC of whichever host responded.

cmd
ping -n 1 192.168.1.50 >NUL
arp -a 192.168.1.50

Output:

sql
Interface: 192.168.1.100 --- 0x4
  Internet Address      Physical Address      Type
  192.168.1.50          00-50-56-ab-cd-ef     dynamic

Compare the MAC address shown against the MAC you expect. If it differs, another device has the same IP.

ARP entry states and ageing

Windows tracks each ARP cache entry through several internal states that govern how long the mapping is trusted and when it is re-validated. The state column is not shown by arp -a (which only reports dynamic or static) but it is visible in the PowerShell view via Get-NetNeighbor.

StateMeaning
ReachableConfirmed live within the last BaseReachableTime (default 30 s)
StaleEntry exists but has not been confirmed recently — next packet triggers re-resolution
ProbeA unicast ARP request has been sent and the OS is waiting for a reply
DelayRe-resolution is queued; entry still usable for a few more packets
PermanentStatic entry from arp -s or netsh ... add neighbors
IncompleteInitial broadcast sent, no reply yet — used for IPs that never responded
UnreachableVerified failure to resolve; next attempt restarts the cycle
powershell
Get-NetNeighbor -AddressFamily IPv4 | Select-Object IPAddress,LinkLayerAddress,State,InterfaceIndex

Output:

arduino
IPAddress       LinkLayerAddress  State      InterfaceIndex
---------       ----------------  -----      --------------
192.168.1.1     00-14-22-01-23-45 Reachable              12
192.168.1.10    00-50-56-AB-CD-EF Stale                  12
192.168.1.255   FF-FF-FF-FF-FF-FF Permanent              12
224.0.0.22      01-00-5E-00-00-16 Permanent              12

The default reachable time is randomised between 15 s and 45 s and can be tuned per-interface (see "Tuning ARP cache timers" below).

PowerShell equivalents

PowerShell exposes the ARP/neighbor cache through the NetTCPIP module, with cmdlets that are scriptable and return structured objects rather than text.

powershell
# List all IPv4 neighbors (equivalent to `arp -a`)
Get-NetNeighbor -AddressFamily IPv4

# Add a static neighbor entry (equivalent to `arp -s`); persists across reboots
New-NetNeighbor -InterfaceIndex 12 -IPAddress 192.168.1.1 `
    -LinkLayerAddress "00-14-22-01-23-45" -State Permanent

# Remove a specific neighbor (equivalent to `arp -d`)
Remove-NetNeighbor -InterfaceIndex 12 -IPAddress 192.168.1.10 -Confirm:$false

# Flush all dynamic IPv4 neighbors on every interface
Get-NetNeighbor -AddressFamily IPv4 -State Reachable,Stale | Remove-NetNeighbor -Confirm:$false

Output:

arduino
ifIndex IPAddress         LinkLayerAddress  State        PolicyStore
------- ---------         ----------------  -----        -----------
12      192.168.1.1       00-14-22-01-23-45 Permanent    ActiveStore

New-NetNeighbor -State Permanent is the modern replacement for arp -s and is the only way to create a static entry that survives a reboot without a startup script.

IPv6 neighbor cache (ND)

ARP is IPv4-only. IPv6 uses the Neighbor Discovery protocol (NDP) defined in RFC 4861, with its own cache that has the same role but a different syntax. arp does not show IPv6 neighbors — use netsh or Get-NetNeighbor -AddressFamily IPv6.

cmd
netsh interface ipv6 show neighbors

Output:

arduino
Interface 12: Ethernet

Internet Address                              Physical Address   Type
--------------------------------------------  -----------------  -----------
fe80::1                                       00-14-22-01-23-45  Stale (Router)
fe80::1a2b:3c4d:5e6f:7a8b                     00-50-56-ab-cd-ef  Reachable
ff02::1                                       33-33-00-00-00-01  Permanent
powershell
Get-NetNeighbor -AddressFamily IPv6 | Where-Object State -ne 'Permanent'

To add a static IPv6 neighbor entry:

cmd
netsh interface ipv6 add neighbors "Ethernet" fe80::1 00-14-22-01-23-45

Output:

rust
Ok.

Tuning ARP cache timers

Windows exposes per-interface ARP cache timers via the registry and netsh. The two values that matter most are the reachable time (BaseReachableTime, default ~30 s) and the dead gateway detection interval. Lowering them speeds up failover when a neighbor's MAC changes; raising them reduces ARP broadcast traffic on stable networks.

cmd
rem View per-interface neighbor cache settings (Vista+)
netsh interface ipv4 show interfaces
netsh interface ipv4 show interface "Ethernet"

Output:

yaml
Interface "Ethernet" Parameters
-------------------------------------------------
IfLuid                              : ethernet_32768
IfIndex                             : 12
State                               : connected
Metric                              : 25
...
Base Reachable Time                 : 30000 ms
Retransmission Interval             : 1000 ms
DAD Transmits                       : 3
cmd
rem Lower reachable time to 5 s for a specific interface (Admin)
netsh interface ipv4 set interface "Ethernet" basereachable=5000

Output:

rust
Ok.

The corresponding registry key is HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<GUID>\ReachableTime for per-interface override.

Detecting ARP spoofing

ARP has no authentication: any host on the LAN can claim any IP by sending a gratuitous ARP. An attacker performing a man-in-the-middle attack will typically poison the cache so that the gateway IP resolves to the attacker's MAC. Detect this by comparing the live cache against a known-good baseline.

cmd
rem Snapshot the cache after boot (trusted)
arp -a > C:\Audit\arp_baseline.txt

rem Later, diff against the live cache
arp -a > C:\Audit\arp_current.txt
fc C:\Audit\arp_baseline.txt C:\Audit\arp_current.txt

Output:

markdown
Comparing files C:\AUDIT\arp_baseline.txt and C:\AUDIT\arp_current.txt
***** C:\AUDIT\arp_baseline.txt
  192.168.1.1           00-14-22-01-23-45     dynamic
***** C:\AUDIT\arp_current.txt
  192.168.1.1           de-ad-be-ef-00-01     dynamic
*****

A change in the gateway MAC is the canonical sign of ARP poisoning. Pin the legitimate MAC with arp -s (or New-NetNeighbor -State Permanent) and audit periodically. Enterprise switches with DAI (Dynamic ARP Inspection) and DHCP snooping enforce this at the network layer.

Sending a gratuitous ARP

Windows does not expose a direct "send gratuitous ARP" command, but you can force one by toggling the IP off and on (which triggers Duplicate Address Detection) or by adding a temporary static neighbor on a foreign IP. The PowerShell Test-NetConnection cmdlet also exercises the ARP layer.

powershell
# Force an ARP probe by querying connectivity to a fresh neighbor
Test-NetConnection -ComputerName 192.168.1.10 -InformationLevel Quiet

# Re-announce the local IP after a clean release/renew
ipconfig /release "Ethernet"
ipconfig /renew "Ethernet"

Output:

graphql
True

Re-renewing a DHCP lease performs DAD which is observable on the wire as a gratuitous ARP — useful when a switch's MAC table needs refreshing after a port move.

Interface-index targeting

When the same subnet appears on two interfaces (multi-homed servers, VPN clients, Hyper-V hosts), arp -s ... <if_addr> pins the static entry to the interface whose IP matches if_addr. Always supply this on multi-homed machines — without it, the static entry is created on every matching interface, with unpredictable wins.

cmd
rem Add a static entry only on the interface with IP 10.0.0.5
arp -s 10.0.0.1 00-aa-bb-cc-dd-ee 10.0.0.5

Output:

csharp
(none — exits 0 on success)

To find the right interface IP, list adapters with ipconfig or read the index from route PRINT.

Proxy ARP

Proxy ARP is a mechanism where a router answers ARP requests for IPs that are not its own — typically used on point-to-point links, hub-spoke VPNs, and some virtualization stacks. Windows enables it per-interface via the registry; it is rarely needed on workstations but appears on RRAS gateways.

cmd
rem Check whether Proxy ARP is enabled on an interface (PowerShell)
powershell -NoProfile "Get-NetIPInterface -InterfaceIndex 12 | Format-List Forwarding"

Output:

yaml
Forwarding : Disabled

To enable proxy ARP on an interface, set EnableProxy=1 under the interface's TCP/IP registry parameters and restart the interface. This is almost never required on a desktop and is a security risk on untrusted networks because it can mask Layer-2 misconfigurations.

Reading ARP traffic with pktmon

When the cache is misbehaving and you need to confirm what is actually on the wire, pktmon (built into Windows 10 1809+) can capture ARP frames without third-party tools.

cmd
rem Filter to ARP (EtherType 0x0806)
pktmon filter add -t ARP --ether-type 0x0806
pktmon start --capture --pkt-size 0
rem Reproduce the problem, then
pktmon stop
pktmon format PktMon.etl -o arp.txt

Output:

python-repl
Logger Name:    PktMon
Provider Name:  Microsoft-Windows-PktMon
...

The resulting arp.txt lists each ARP request/reply with source and destination MAC/IP, identifying who is replying for a given address and exposing spoofers or misconfigured hosts.

Common pitfalls

  1. Static ARP entries do not survive a reboot by defaultarp -s entries are stored only in the in-memory cache; to make them persistent, add them in a startup script or use New-NetNeighbor -State Permanent (modern) / netsh interface ipv4 add neighbors (legacy).
  2. arp -d * requires elevation on Vista+ — running without Administrator returns "The requested operation requires elevation"; right-click cmd.exe → Run as administrator.
  3. ARP operates per-interface — on multi-homed machines, the same remote IP may appear in different interface tables with different entries; use -N to target the correct one.
  4. Dynamic entries expire automatically — Windows expires dynamic ARP entries after a few minutes of inactivity; if a host keeps changing IP (e.g. DHCP lease renewal), the cached entry updates automatically.
  5. ARP does not cross routersarp -a only shows Layer 2 neighbours on directly connected subnets; hosts behind a router appear only with the router's MAC (the next-hop gateway), not the host's own MAC.
  6. arp -s on Win10+ may report "The ARP entry addition failed: Access is denied" — Windows requires the interface to be administratively up and the address family enabled; verify with netsh interface ipv4 show interfaces.
  7. MAC format is dash-separatedarp -s accepts 00-14-22-01-23-45 (dashes) but rejects 00:14:22:01:23:45 (colons); PowerShell New-NetNeighbor accepts both.
  8. Hyper-V/WSL bridged adapters add noisearp -a lists every virtual interface; pipe through findstr to focus on the physical adapter.
  9. arp -s does not validate the MAC against the actual host — you can pin any MAC to any IP; double-check the MAC matches a real device on the segment before locking it in.
  10. ARP is IPv4 only — for IPv6, use netsh interface ipv6 show neighbors or Get-NetNeighbor -AddressFamily IPv6; arp -a returns no IPv6 entries.

Real-world recipes

Confirm MAC address of the default gateway

cmd
for /f "tokens=3" %G in ('ipconfig ^| findstr "Default Gateway"') do set GW=%G
ping -n 1 %GW% >NUL
arp -a %GW%

Output:

sql
Interface: 192.168.1.100 --- 0x4
  Internet Address      Physical Address      Type
  192.168.1.1           00-14-22-01-23-45     dynamic

Pin the gateway MAC to prevent ARP spoofing

cmd
@echo off
set GW_IP=192.168.1.1
set GW_MAC=00-14-22-01-23-45
arp -d %GW_IP% 2>NUL
arp -s %GW_IP% %GW_MAC%
echo Static ARP entry set for gateway %GW_IP% → %GW_MAC%

Output:

sql
Static ARP entry set for gateway 192.168.1.100-14-22-01-23-45

List all dynamic ARP entries

cmd
arp -a | findstr "dynamic"

Output:

csharp
  192.168.1.1           00-14-22-01-23-45     dynamic
  192.168.1.10          00-50-56-ab-cd-ef     dynamic

Build a CSV inventory of all neighbors

A typed inventory is far easier to diff than arp -a text. PowerShell can produce a CSV with hostname enrichment for asset management.

powershell
Get-NetNeighbor -AddressFamily IPv4 |
    Where-Object State -in 'Reachable','Stale' |
    Select-Object @{n='Host';e={$env:COMPUTERNAME}}, IPAddress, LinkLayerAddress, State,
        @{n='Interface';e={(Get-NetAdapter -InterfaceIndex $_.InterfaceIndex).Name}} |
    Export-Csv -NoTypeInformation -Path C:\Audit\arp_inventory.csv

Output:

css
(none — writes CSV)

Audit gateway MAC and alert on change

A scheduled task can compare the live gateway MAC against a pinned expected value and write an event to the log when they diverge — a poor man's IDS for ARP spoofing.

cmd
@echo off
setlocal
set GW_IP=192.168.1.1
set EXPECTED_MAC=00-14-22-01-23-45
for /f "tokens=2" %%m in ('arp -a %GW_IP% ^| findstr %GW_IP%') do set ACTUAL_MAC=%%m
if /i "%ACTUAL_MAC%"=="%EXPECTED_MAC%" (
    echo Gateway MAC OK: %ACTUAL_MAC%
) else (
    echo *** GATEWAY MAC CHANGED *** expected %EXPECTED_MAC%, got %ACTUAL_MAC%
    eventcreate /T WARNING /ID 800 /L APPLICATION /SO ARPAudit /D "Gateway MAC changed to %ACTUAL_MAC%"
)
endlocal

Output:

yaml
Gateway MAC OK: 00-14-22-01-23-45

Sweep a subnet to populate the cache

Force ARP entries for every live host on the LAN by pinging each address once. Useful before running arp -a to take a snapshot.

cmd
@echo off
for /l %%i in (1,1,254) do (
    start /b /min ping -n 1 -w 200 192.168.1.%%i >NUL
)
ping -n 5 127.0.0.1 >NUL
arp -a | findstr dynamic

Output:

csharp
  192.168.1.1           00-14-22-01-23-45     dynamic
  192.168.1.5           00-50-56-aa-bb-01     dynamic
  192.168.1.10          00-50-56-ab-cd-ef     dynamic
  192.168.1.50          de-ad-be-ef-00-01     dynamic
  ...

Force re-resolution of a single host

Removing the cache entry forces Windows to broadcast a fresh ARP request on the next packet, which is the cheapest way to refresh a stale mapping without disturbing other entries.

cmd
arp -d 192.168.1.50
ping -n 1 192.168.1.50 >NUL
arp -a 192.168.1.50

Output:

sql
Interface: 192.168.1.100 --- 0x4
  Internet Address      Physical Address      Type
  192.168.1.50          00-50-56-aa-bb-02     dynamic

Persist a pinned gateway entry across reboots

Static entries added with arp -s are wiped on reboot. To make the entry permanent, register a scheduled task at startup or use New-NetNeighbor -State Permanent directly — the latter is registry-backed and survives reboots without any helper script.

powershell
# Run once as Administrator
$ifIdx = (Get-NetAdapter -Name "Ethernet").ifIndex
New-NetNeighbor -InterfaceIndex $ifIdx -IPAddress 192.168.1.1 `
    -LinkLayerAddress "00-14-22-01-23-45" -State Permanent

Output:

arduino
ifIndex IPAddress     LinkLayerAddress  State     PolicyStore
------- ---------     ----------------  -----     -----------
12      192.168.1.1   00-14-22-01-23-45 Permanent ActiveStore

Capture ARP storms

A flood of ARP requests can indicate a misbehaving switch, a loop, or a scanning worm. Quickly count the ARP request rate to confirm.

cmd
pktmon filter add ARP --ether-type 0x0806
pktmon start --capture --pkt-size 0
timeout /t 10 >NUL
pktmon stop
pktmon format PktMon.etl | findstr /c:"who has" | find /c /v ""

Output:

code
247

247 ARP queries in 10 seconds (~25/s) is well above the 1–2/s baseline of a quiet LAN and warrants investigation. Identify the source by formatting the capture: pktmon format PktMon.etl -o storm.txt and inspect the sender MAC distribution.

Compare two snapshots over time

A daily snapshot enables drift detection — useful in security-conscious environments where a stable LAN should not see MAC changes.

cmd
@echo off
set TS=%date:~-4,4%-%date:~-10,2%-%date:~-7,2%
arp -a > C:\Audit\arp_%TS%.txt
forfiles /p C:\Audit /m arp_*.txt /d -7 /c "cmd /c del @path" 2>NUL
echo Snapshot saved: arp_%TS%.txt

Output:

yaml
Snapshot saved: arp_2026-05-24.txt

Sources

Microsoft Learn — arp command — Official syntax, parameter table, examples, and remarks for the Windows arp command.

See also

  • ipconfig — view interface IPs and DNS configuration
  • ping — trigger ARP resolution by sending an ICMP echo
  • route — IP routing table (Layer 3 forwarding decisions)
  • getmac — read the local machine's MAC addresses
  • netstat — active TCP/UDP connections, often used alongside ARP
  • netshnetsh interface ipv4 show neighbors is the netsh equivalent of arp -a