Back

Blog details

Anatomy of a CID: Decoding an IPFS Identifier

AIOZ Network
5 min readAugust 22, 2026
aioz-pin

A CID looks like noise until you know what you are looking at: bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi or QmYwAPJzv5CZsnAztbSyJmvxG7hcTMBBg9uCPQpNyH1KAF. Both are valid IPFS CIDs, and both encode real, decodable information: a version, a format, and a hash, not just an opaque fingerprint. This breaks a CID down field by field so a string like that stops looking like noise. It is a companion piece to an earlier article on this blog about verifying a CID yourself; this one is about what the identifier is actually made of, not how to recompute it.

TL;DR:

  • A CID has two live versions in use: CIDv0 (the old default, always base58, always starts with "Qm") and CIDv1 (multibase-prefixed, codec-aware, the current default for new content)
  • CIDv1 packs four pieces into one string: a multibase prefix (how the rest is text-encoded), a version number, a multicodec (what format the linked content is in), and a multihash (which hash algorithm plus the digest itself)
  • The hash inside a CID is the hash of the root block of a file's Merkle DAG, not a direct hash of the file's raw bytes
  • CIDv0 strings always decode to sha2-256 hashes of dag-pb-formatted data, since CIDv0 predates the ability to specify either field
  • AIOZ Pin's API returns CIDs from every pinning call; decoding one tells you exactly what hash algorithm and format you are looking at without needing to trust the string blindly

Two Versions, One Underlying Idea

Every CID identifies a piece of content by hashing it, but the two versions in active use encode that differently. CIDv0 is the older, simpler format: always base58-encoded, always 46 characters, always starting with "Qm." It has no way to specify a hash algorithm or content format inside the string itself, both are implicitly fixed (sha2-256, dag-pb) because CIDv0 predates the idea of making them configurable. CIDv1 replaced that with a fully self-describing structure, at the cost of being longer and less immediately recognizable at a glance. New content on IPFS defaults to CIDv1 today; CIDv0 strings still show up constantly because plenty of already-pinned content was hashed before the switch, and both remain valid, permanently, since a CID's whole purpose is to be a stable reference.

The Four Parts of a CIDv1

A CIDv1 string, once decoded, breaks into four distinct fields:

  1. Multibase prefix: the first character of the string, indicating how everything after it is text-encoded. A CID starting with b is base32 (the default for CIDv1), one starting with z is base58btc. This exists because a CID needs to survive being pasted into a URL, a filename, or a QR code, and different contexts tolerate different character sets.
  2. Version: a single number, 1 for CIDv1, encoded right after the multibase prefix is stripped off.
  3. Multicodec: an identifier saying what format the content the CID points to is in. Common values: dag-pb (0x70, the format used for UnixFS files and directories), raw (0x55, an unstructured block with no linking metadata), dag-cbor (0x71, used for structured linked data like the ERC-8004 registration files covered elsewhere on this blog). This is what lets software know how to interpret whatever it fetches, rather than guessing.
  4. Multihash: the actual hash, itself two parts: an algorithm identifier (sha2-256 is the common default, though the format supports others) and the digest, the fixed-length output of running that algorithm.

CIDv0 skips all of this self-description: it is always base58, always version implicitly 0, always dag-pb, always sha2-256, so a CIDv0 string is really just the multihash on its own, with everything else fixed by convention rather than encoded.

What the Hash Actually Hashes

A CID's multihash is not a hash of a file's raw bytes end to end. It is the hash of the file's root block, the top node of its Merkle DAG. For a small file that fits in one block, those two things happen to be close to the same thing. For a large file split into many blocks, the root block itself is mostly a list of links to child blocks, each identified by its own CID, so the root's hash depends on the hashes of everything beneath it without directly containing the file's bytes at all. This is the same property covered in this series' first article: change one byte anywhere in the file, and the change propagates up through every parent hash to the root, giving you a different CID.

Decoding a Real CID

Take bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi apart:

  • b, multibase: base32
  • What follows decodes to: version 1, codec dag-pb (0x70), multihash algorithm sha2-256, then the 32-byte digest itself

Every part of that is recoverable from the string alone, with a CID-decoding library (available in the same @aioznetwork/aioz-pin-sdk dependency tree via the underlying multiformats/cid packages, or standalone via js-multiformats) rather than by trusting a written explanation of what a given prefix "usually" means.

Where This Shows Up on AIOZ Pin

Every pinning call on AIOZ Pin, pinFilesToIPFS(), pinFolderToIPFS(), pinByHash(), returns a CID identifying what got pinned. Knowing how to decode it tells you, directly from the string, what hash algorithm secures that content and what format it is stored in, without needing to take AIOZ Pin's word for it or dig through a dashboard. This matters most for anything you plan to verify independently later, an NFT's metadata file, an ERC-8004 registration file, a dataset you need to prove has not changed, since the CID itself is the durable, checkable record of exactly what you pinned.

Frequently Asked Questions

What is a CID in IPFS? A Content Identifier: a self-describing string that identifies content by the hash of its root Merkle DAG block, along with metadata about which hash algorithm and content format were used.

What is the difference between CIDv0 and CIDv1? CIDv0 is always base58-encoded, 46 characters, and implicitly sha2-256/dag-pb with no way to specify otherwise. CIDv1 is multibase-prefixed and explicitly encodes its version, content codec, and hash algorithm, and is the current default for new content.

Does a CID hash the whole file directly? No. It hashes the file's root Merkle DAG block, which for a multi-block file is mostly links to child blocks, each identified by their own hash, rather than the file's raw bytes directly.

Why do some CIDs start with "Qm" and others with "b"? "Qm" indicates CIDv0 (base58-encoded). "b" indicates CIDv1 encoded in base32, the current default text encoding for new CIDs.

Can two different files ever produce the same CID? Only in the case of a hash collision, which is why IPFS relies on cryptographic hash functions like sha2-256, where finding two inputs with the same output is computationally infeasible.

Does AIOZ Pin use a custom CID format? No. AIOZ Pin returns standard IPFS CIDs from its pinning API, decodable with any standard CID library, not a proprietary identifier format.

References

We only send updates when meaningful changes ship, and you can unsubscribe anytime

Related Content

blog thumbnail

How IPFS Splits Files: Fixed vs. Content-Defined Chunking

IPFS defaults to 256 KiB fixed-size chunks, but also ships Rabin and Buzhash content-defined chunkers. Here is why the choice affects deduplication.

5 min readAugust 23, 2026
blog thumbnail

Anatomy of a CID: Decoding an IPFS Identifier

An IPFS CID is not a random string. It encodes a version, a codec, and a hash algorithm plus digest. Here is how to decode a real CID piece by piece.

5 min readAugust 22, 2026
blog thumbnail

How IPFS Shards Large Directories: The HAMT, Not a B-Tree

IPFS does not use a B-tree for large directories. It uses a HAMT, a Hash Array Mapped Trie. Here is exactly how it shards a folder once it outgrows one block.

5 min readAugust 21, 2026
blog thumbnail

How to Resize Images on AIOZ Pin Using URL Parameters

AIOZ Pin image resizing happens straight in the gateway URL, no upload step or separate service. Here is every img- parameter, with real srcset examples.

5 min readAugust 19, 2026
blog thumbnail

How x402 Payments Weight AI Agent Reputation on ERC-8004

x402 payments let ERC-8004 weight a paid AI agent interaction more heavily than free work in its reputation score. Here is exactly how that link works.

5 min readAugust 18, 2026
blog thumbnail

How to Automate NFT Pinning with the AIOZ Pin NFT API

AIOZ Pin NFT API calls pin an asset and its metadata as two tracked pins under one record. Here is how to automate it directly over REST, no SDK needed.

5 min readAugust 17, 2026