
IPFS finds and retrieves files in two steps. The DHT answers "who has this CID?" by storing provider records on the 20 peers closest to it, and Bitswap then fetches the blocks from those peers with want-have and want-block messages.
TL;DR:
SHA256(multihash). To find content, a node walks toward that same spot.want-have. Only when none of them has the block does it fall back to a DHT lookup.Updated Oct 28, 2026: answer-first opening, a step-by-step lookup diagram, Kubo commands to watch the DHT and Bitswap on your own node, provider record expiry, and a corrected AIOZ Pin section based on our docs.
A URL names a server, so your browser knows where to connect before it asks for anything. A CID names content, and that content could sit on one peer, on a thousand peers, or on nobody at the moment. Before any bytes move, your node has to answer a different question: which peers hold this CID right now?
IPFS answers it with a shared lookup table that every participating node helps store. A central registry would be faster to build, but it would put one company back in control of what can be found. The DHT spreads that job across the network instead.
The IPFS DHT is based on Kademlia. Your node's position in the address space is SHA256(PeerID), read as a number between 0 and 2256 - 1. A record's position is the SHA-256 of its key, so a block with multihash H lives near SHA256(H). Distance between two positions decides which peers are responsible for which records.
Announcing content is called a provider PUT: your node looks up the K closest peers to SHA256(H), where K is 20 in IPFS, and stores a provider record on each of them. It also keeps a copy itself. The IPFS docs add one rule: a node may only put a provider record for itself, so Alice can't announce that Bob has a file.
Finding content is a provider GET. Your node asks peers near SHA256(H) two things at once: which closer peers they know, and whether they hold a record for H. Each answer moves the search closer, and the lookup takes about O(log N) steps for a network of N peers.
Why 20 peers and not one? Peers join and leave all the time. The IPFS docs explain that K is chosen from observed churn and the republish rate, so a record survives when some of its holders go offline.
Bitswap is the message-based protocol IPFS uses to swap blocks, and every message carries a want-list, blocks, or both. Each node remembers what its peers want and sends a block along when it gets one that a peer asked for.
A fetch starts with the root block of the file. Your node sends want-have for its CID to every peer it is already connected to. Peers that hold it answer have and join a session for this download, while the rest answer dont-have. Your node then sends want-block to peers that said yes, and they reply with the block.
If none of your current peers has the root block, Bitswap asks the DHT who can provide it, connects to those peers, and repeats the exchange. After the root arrives, your node reads the child CIDs from it and keeps asking the same session for the rest. Several peers can serve different blocks of one file at the same time.

The two protocols solve different problems at different costs. A DHT lookup crosses the network and takes several round trips, which is fine once per file but wasteful for every block. Bitswap works over connections you already have, so asking a neighbor first is cheap. A peer that has the root block often has the children too, which is why Bitswap keeps asking the same session.
The split also keeps each part simple. The DHT stores small records saying who has what, and never moves file data; Bitswap moves file data and never has to know the whole network. You see the result as one download, even though two protocols took turns behind it.
A provider record is not permanent: records on the public Amino DHT expire after a fixed validity window, so a node that wants to stay findable has to announce again. Kubo's Provide.DHT.Interval defaults to 22 hours, which its config docs describe as about half of that window. Our post on why provider records expire and get renewed covers the timing in detail.
Kubo also doesn't rely on the DHT alone anymore. With the default Routing.Type of auto, it queries the Amino DHT and HTTP routers together for faster lookups. Delegated routing explains how those HTTP routers work.
If you run Kubo, three commands from its CLI reference show these steps live. We have no IPFS binary on this machine, so these were not run and no output is shown. Replace <CID> with any CID you want to inspect.
# DHT: list peer IDs that provide a CID (default: up to 20)
ipfs routing findprovs <CID>
# Bitswap: blocks your node is waiting for right now
ipfs bitswap wantlist
# Bitswap: counters for blocks and data sent and received
ipfs bitswap stat --humanRun findprovs on a CID that nobody pins and you will often get an empty list, which is the gap pinning services exist to fill.
Content you pin with AIOZ Pin "becomes available on the public IPFS network", according to our gateway docs, and anyone running an IPFS node can access it through their own node. That means the DHT and Bitswap steps above are how other IPFS nodes reach your pinned files. Our docs don't describe how AIOZ Pin announces provider records.
For HTTP access, you skip running a node and use a gateway. The public gateway is meant for testing, with limits of 15 requests per minute per CID and 200 per minute per IP. Premium gateways have no predefined rate limit and serve from 200+ edge-caching locations, according to the AIOZ Pin docs.
Routing also matters when you pin a CID that is already on IPFS. AIOZ Pin can only store blocks it can find and fetch from nodes that hold them, and the docs list a Failed status for when "the graph of data is incomplete". This is the documented pin-by-CID request (not run here, no credentials on this machine):
curl --location --request POST 'https://api.aiozpin.network/api/pinning/pinByHash' \
--header 'pinning_api_key: KEY' \
--header 'pinning_secret_key: SECRET' \
--header 'Content-Type: application/json' \
--data-raw '{ "hash_to_pin": "<CID>", "metadata": { "name": "my-file" } }'Gateway limits and URLs are on the AIOZ Pin limits page.
How does IPFS find content without a central server? A Kademlia DHT stores provider records on the 20 peers closest to the hash of each CID's multihash, and your node walks toward those peers to read the records.
What is a provider record? A small record saying "this peer can provide this multihash", stored on the K closest DHT peers and on the providing node itself.
What is Bitswap in IPFS? The block exchange protocol. Your node sends want-have and want-block messages, and peers that hold the blocks send them back.
Does Bitswap always use the DHT? No. It asks connected peers first and only queries the DHT when none of them has the root block.
Can a node announce content for another node? No. A node may only put provider records that name itself.
Why can't my IPFS node find a CID? Usually no online node is providing it, or its provider records expired. Keeping it pinned on an always-on node that reprovides fixes both.

An IPFS dedicated gateway on AIOZ Pin is called a premium gateway. See what the free plan limits, what a paid plan adds, and what happens at zero balance.

Pin by CID asks a pinning service to fetch content already on IPFS and keep it. Covers the AIOZ Pin pinByHash call, statuses, and why a pin stalls on Pinning.

IPFS gateway not working? Read the status code first, then check the CID, your request rate, and whether anyone is providing the content. Here is the order.

ERC-1155 metadata on IPFS breaks when filenames ignore the {id} rule. Here is the exact 64-character format, a working folder layout, and the per-token option.

AIOZ Pin rate limits in one place: 180 requests per minute for the API, 15 per CID on the public gateway, and no predefined limit on premium gateways.

IPFS pin stuck on Pinning? Here is what Pinning, Pinned, and Failed mean on AIOZ Pin, why big directories can sit there, and how to read a pin's real state.