GitHunt
RE

refcell/arlo

Batteries Included P2P Beacon and Execution RPC Discovery for Ethereum and Base. Built in Rust.

arlo

P2P-based RPC URL discovery for Ethereum and Base networks.

cargo install arlo

Why?

Need an execution RPC or Beacon url for a network but don't have one?

Arlo's got you.

Want to use a stack of RPC urls to create a robust provider service?

Arlo's got you.

Demo

base-mainnet-demo.mov
Screen.Recording.2026-03-11.at.4.11.47.PM.mov

Usage

Scan for RPC endpoints on Ethereum mainnet and Base mainnet (the default):

arlo scan

Scan a specific network, or multiple networks at once:

arlo scan --chain eth-mainnet
arlo scan --chain eth-mainnet,base-mainnet,eth-sepolia

Scan for a fixed duration (seconds) instead of running forever:

arlo scan --chain eth-mainnet --duration 60

Only surface endpoints that expose specific namespaces:

arlo scan --chain eth-mainnet --namespace eth,debug,trace

Write discovered URLs to a file as well as stdout:

arlo scan --chain eth-mainnet --output urls.txt

Once you have a list of discovered endpoints stored in ~/.arlo/, start the proxy:

arlo proxy

The proxy walks you through selecting a network, an RPC type (execution, beacon, or rollup), and which specific backends to include. It then binds a local HTTP server you can point any JSON-RPC client at. You can also skip the interactive prompts:

arlo proxy --network eth-mainnet --port 8888
arlo proxy --network eth-mainnet --port 8888 --flood

In flood mode every request is fanned out to all selected backends simultaneously and the fastest successful response is returned to the caller. In the default sequential mode backends are tried one at a time in order, falling through to the next on any error or non-200 response.

Print every supported EVM chain and its chain ID:

arlo chains

How it works

Ethereum mainnet and Ethereum Sepolia use the discv4 peer discovery protocol. Arlo runs up to 32 concurrent discv4 tasks, each with its own UDP socket, bonding with remote nodes by exchanging PING and PONG packets and then issuing FINDNODE to collect neighbor lists. Because discv4 requires mutual bonding before a node will answer FINDNODE, Arlo completes the full handshake (our PING, their PONG, their PING, our PONG) before requesting neighbors. This yields roughly 25 newly seen node addresses per second across the task pool.

Base mainnet and Base Sepolia are OP Stack chains and use discv5 instead of discv4. Arlo bootstraps into discv5 by converting each bootnode's secp256k1 public key into a libp2p PeerID, building a multiaddr, requesting the node's signed ENR, and then issuing FINDNODE queries from there.

Every IP address that surfaces from either discovery path is sent to the prober. The prober attempts an HTTP JSON-RPC connection on a set of common ports (8545, 8546, 9545, 8547 by default). If a port responds, Arlo calls eth_chainId to confirm the network, rpc_modules to enumerate exposed namespaces, eth_syncing to check sync status, and web3_clientVersion to fingerprint the client. Endpoints that pass all checks are printed to stdout in real time and appended to ~/.arlo/<network>/rpcs.json.

Alongside execution RPC probing, Arlo probes for beacon REST API endpoints on L1 chains and for OP Stack rollup node endpoints on L2 chains. Beacon nodes are identified by querying /eth/v1/config/spec and /eth/v1/node/version. Rollup nodes are identified by calling optimism_syncStatus and optimism_outputAtBlock.

Discovered peer IPs are also saved to ~/.arlo/<network>/bootstore.json and reloaded as seed peers on the next run, so each scan starts with a warm set of known-good addresses and reaches useful results faster over time.

The proxy subcommand reads whichever rpcs.json files you have accumulated and starts a local HTTP server using axum. Sequential mode forwards each incoming request to backends one at a time, returning the first HTTP 200 it receives and moving on to the next backend only if a connection fails or the response is not 200. Flood mode spawns one concurrent request per backend using a tokio JoinSet, returns the body from whichever backend responds first with 200, and cancels the remaining in-flight requests. Both modes forward the full request path so that beacon REST calls like GET /eth/v1/beacon/headers are routed correctly alongside ordinary JSON-RPC POST requests.

License

MIT

Languages

Rust98.0%Just2.0%

Contributors

MIT License
Created March 11, 2026
Updated March 11, 2026
refcell/arlo | GitHunt