Insights

How to Mint NFTs on the XRP Ledger

Minting an NFT on the XRP Ledger stores one link, at most 256 bytes long. Everything a person sees sits wherever that link points, so the link is the whole thing. Most XRPL creators already get this right — and the ones who do not have handed the artwork to whoever runs a web server.

Measured 2026-09-04Census of 8,618,070 NFTs

What XRPL creators actually do

Where the art actually lives
IPFS (ipfs:// link)IPFS (ipfs:// link) — 2,263,313 NFTs, 67.2%67.2% 2,263,313via issuer APIvia issuer API — 370,286 NFTs, 11.0%11.0% 370,286IPFS (gateway URL)IPFS (gateway URL) — 242,954 NFTs, 7.2%7.2% 242,954plain web serverplain web server — 213,674 NFTs, 6.3%6.3% 213,674IPFS (bare CID)IPFS (bare CID) — 80,753 NFTs, 2.4%2.4% 80,753via issuer IPFS foldervia issuer IPFS folder — 78,474 NFTs, 2.3%2.3% 78,474Arweave (arweave.net)Arweave (arweave.net) — 72,115 NFTs, 2.1%2.1% 72,115on the ledger itselfon the ledger itself — 26,695 NFTs, 0.8%0.8% 26,695otherother — 11,565 NFTs, 0.3%0.3% 11,565nothing on-chainnothing on-chain — 6,593 NFTs, 0.2%0.2% 6,593ar://36 NFTs — none of them load
leads to content nobody can swap, no company neededthe ledger names a company, which names the filesomeone else decides what it returns
Every NFT on the ledger except expo-2025-dwnft, which is 5,251,612 NFTs on its own — 60.9% of the ledger, all on one web server. Counting it, a plain web server holds 63.4% and the addressed rows 30.9%: one minter, not a practice.

93% of XRPL NFTs hold artwork that nobody can substitute, almost all of it on IPFS. Only 6.3% sit on a plain web server where the picture can be changed or removed. That holds where the money is, too: of the twenty collections with the most XRP ever traded, 18 keep their art on IPFS and 2 do not.

The 20 highest-volume collections, by lifetime XRP traded
1xpunks
2cryptoland
3bored-apes-xrp-club
4fuzzybears
5xspectar
6rpb5vnq…
7blockchain-backer
8revellers
9ripplepunks
10fortunes-tier
11sraebyzzuf
12zerpmon
13unixpunks
14cac
15eden-digital-real-estate
16bearxrpl
17xshrooms
18hogs
19xroyalty
20xrp-name-service
IPFS, named on the NFTIPFS, via the issuer's APIplain web server
18 of 20 keep their art on IPFS — 14 reachable without asking anyone (one of those through an IPFS folder its issuer publishes), 4 only through a company's API. Just 2 sit on a plain web server.

The split inside that good news is what the rest of this article is about. 82% name the artwork on the ledger, in a form any reader can follow without asking permission. The other 11.0% reach it only through an address a company publishes — including the single biggest collection on the ledger by volume.

Why a plain web link defeats the point

The ledger does not store your artwork. It stores a pointer to it, and it makes no promise about what sits at the other end. There is no fingerprint of the file recorded anywhere in the transaction, so nothing can tell whether the image served today is the image that was minted.

In 2022 the cryptographer who built the Signal messenger, Moxie Marlinspike, minted an NFT to prove the point. "What surprised me about the standards was that there's no hash commitment for the data located at the URL," he wrote — no fingerprint, so nothing to check the file against.

His NFT "changes based on who is looking at it, since the web server that serves the image can choose to serve different images based on the IP or User Agent of the requester." One picture on one marketplace, a different picture on another, and "when you buy it and view it from your crypto wallet, it will always display as a large 💩 emoji."

Then the marketplace deleted it, and "after OpenSea removed my NFT, it also no longer appeared in any crypto wallet on my device." A token he still owned showed him nothing at all.

Nothing about that is specific to Ethereum. Any XRPL NFT whose link is a plain web address has the same property: the person who controls that domain owns the artwork, and the person who owns the token owns a sentence describing where it used to be. The domain does not even have to be sold or attacked — it only has to expire.

What the ledger guarantees, and what it does not
ON THE LEDGERWHEREVER THE LINK POINTSNFT objectone link, up to 256 bytesmetadata filename, traitsthe imagethe part people seeyours, permanentlychangeable by whoever hosts itunless the link is a hash of the file itself
The ledger keeps the first box for as long as the ledger exists. On a plain web address, the other two belong to whoever runs the server.

A content address fixes this, and it is the whole reason IPFS and Arweave exist. An IPFS identifier is derived from the bytes of the file itself: change one pixel and it is a different identifier, so a link of that form can only ever return the file that was minted, or nothing at all. That is a promise a web address cannot make at any price.

The gateway trap

One group in the chart deserves its own warning, because it looks fine and is half right. 395,822 NFTs — around 12% — store their art on IPFS or Arweave but write the link as an ordinary web address, like https://ipfs.io/ipfs/bafy… or https://yourname.mypinata.cloud/ipfs/Qm….

The file itself is safe: the identifier is right there in the address, so nobody can swap the picture. What is fragile is the way there — that address depends on one company's gateway staying online, and keeping the same URL shape forever.

IPFS's own guidance is blunt about it — gateway links "should not be the primary or canonical link to your data", because "a gateway link can fail if the gateway operator goes offline".

The fix costs nothing at mint time: write ipfs://bafy… instead. Same file, same identifier, no company in the middle. Any viewer can then pick whichever gateway works today.

When the NFT carries no link at all

The collection with more XRP traded through it than any other, XPUNKS, has no link on its NFTs at all. Nothing on the token says where the picture is. What it has instead is a field on the issuing account: every XRPL account can publish a Domain, and this issuer's reads https://marketplace-api.onxrp.com/api/metadata/. Add the NFT's id to the end of it and the metadata comes back.

$ curl https://marketplace-api.onxrp.com/api/metadata/00081B58…00000000

{ "name": "XPUNKS #0",
  "description": "More than a JPEG. Currently on Earth, on-chain and on the Moon.",
  "image": "ipfs://QmQRMmLu2Cr4yvQ3mNcxnYBaSwgyBVYEsaJUrrBShnTzRq",
  … }

So the artwork is on IPFS after all, and safe from being swapped. What is missing from the ledger is the map — which picture belongs to which token. 370,286 NFTs are held this way, 322,343 of them through that one address, and four of the twenty biggest collections by volume are among them.

It beats a plain web server, and it is still a dependency. The address is an ordinary account field, so one transaction repoints an entire collection at once. That transaction is public, but nothing about the NFTs changes — a holder watching their own token sees no event at all.

And the address on the ledger still names onXRP, a brand that has since become BIDDS. The request is answered today only because a redirect to api.bidds.com is being maintained for it.

The same idea, done without a company

Eden Digital Real Estate, also among the twenty biggest, sets its issuer Domain to ipfs://QmW2MNkq7VhJkKhG2iua3GfMDGnCFet6ELgvVBBELu99bJ/. Not an API — an IPFS folder. Inside it sit 9,039 files, one per NFT, each named after that NFT's id, and each naming an image that is itself on IPFS.

$ curl https://ipfs.io/ipfs/QmW2MNkq7…/000809C42A…00000000.json

{ "name": "Eden Pre-fab 15-A-6",
  "image": "ipfs://QmYFtDNMCMNh4JJuKbisR8eaqu7DcXD5RhrydkFur5eG3V",
  … }

That is the same shape as the API version with the company taken out of it. The map from token to picture is one content-addressed object: anyone can pin the whole collection, it cannot be altered, and it stays recoverable from its identifier alone. An API answer is not — nobody archives API responses. 78,474 NFTs are held this way, against 370,286 through a company's API.

It also keeps what made the pattern attractive in the first place. Until recently a link written onto an NFT was frozen for good, and pointing the Domain at a new folder was the only way to fix a bad one.

That constraint is gone: tfMutable now does the same job, one signed transaction per NFT, publicly on the ledger. Minting today, put the link on the NFT and set that flag — the fixability, without asking anyone to keep a server or a convention alive on your behalf.

Minting one, step by step

If you are not sure you want to do this yourself, don't. Each of these takes your artwork and handles the storage, the metadata and the mint for you, and several others do the same. It costs a fee and it is the right choice for most people — the rest of this section is for anyone who would rather own the process.

1

Upload the artwork and take its identifier

Add the image to IPFS through a pinning service and keep the content identifier, or CID — the long string that stands for the file.

IPFS's own guidance is to use version 1 CIDs in base32: the long bafy… form, not the older Qm… one.

2

Write the metadata file

A small JSON document naming the image, following XLS-24, the XRPL's metadata standard. Reference the image as ipfs://…, not as a gateway address, for the reason above.

{
  "schema": "ipfs://bafkreidkzqkzqjcxmhwq7fjmqvcnzsuu4vejfyzsecqvpwcnwq4d3ovpxu",
  "nftType": "art.v0",
  "name": "Example #1",
  "description": "One sentence about the piece.",
  "image": "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi/1.png",
  "collection": { "name": "Example", "family": "Example" },
  "attributes": [{ "trait_type": "Background", "value": "Blue" }]
}
3

Upload the metadata file too, and pin both

Pinning is the part people skip. An unpinned file is deleted whenever the node holding it needs the space, so "it is on IPFS" means nothing until somebody has promised to keep it.

Use a service built for it — Pinata and Filebase are the two most XRPL collections rely on — and use two of them, because one pinning service is one company.

4

Send the mint

The NFT points at the metadata file, not at the image. The URI is hex-encoded and must be 1 to 256 bytes — an empty one is rejected outright. An ipfs:// link in the form above is 66 bytes, so there is room to spare.

import { Client, Wallet, convertStringToHex } from 'xrpl';

const client = new Client('wss://xrplcluster.com');
await client.connect();

// sEd… seeds are ed25519, every other s… seed is secp256k1.
const wallet = Wallet.fromSeed(seed, {
  algorithm: seed.startsWith('sEd') ? 'ed25519' : 'ecdsa-secp256k1',
});

const res = await client.submitAndWait({
  TransactionType: 'NFTokenMint',
  Account: wallet.address,
  URI: convertStringToHex('ipfs://bafkreih5aznjvttude6c3wbvqeebb6rlx5wkbzyppv7garjiubll2ceym4'),
  NFTokenTaxon: 1,           // with Account above, this pair IS the collection
  TransferFee: 5000,         // 5.000% royalty — needs tfTransferable below
  Flags: 0x01 | 0x08 | 0x10, // burnable + transferable + mutable
  Fee: '12',
  SourceTag: 12345678,       // pick one number, use it on every mint
}, { wallet });

console.log(res.result.meta.TransactionResult);  // tesSUCCESS
console.log(res.result.meta.nftoken_id);         // the NFT you just created

Four of those fields are worth understanding before you send a thousand of them.

  • TransferFee is your royalty, from 0 to 50000, meaning 0% to 50%. Set one without tfTransferable and the transaction fails outright rather than minting without it.
  • tfMutable is the only thing that ever lets you change the link, through a later NFTokenModify. Leave it off and a broken link stays broken for good.
  • NFTokenTaxon is half of what identifies a collection. The other half is the issuing account, and both are packed into every NFT's id, so a collection is the pair — your taxon 1 and somebody else's taxon 1 are unrelated. Give every piece in a series the same number and mint them all from the same account.
  • nftoken_id comes back in the transaction result. That is the only place you get it, so read it there or you will have to go looking.

Minting costs 12 drops in fees, plus 0.2 XRP held in reserve for each page of up to 32 NFTs. The field-by-field rules are in the NFTokenMint reference, and every limit quoted here is enforced in the server's own checks.

5

Check the link before minting the rest

Fetch your own URI, confirm the metadata comes back, then fetch the image it names. Mint one, look at it on a marketplace, and only then mint the collection.

The rest of the toolkit

Minting is one of six transactions, and four flags decided at mint time govern what the other five may do. Every rule below is enforced by the server, so none of it is a marketplace convention you can opt out of.

TransactionWhat it does, and who may send it
NFTokenMintCreates the token. Add an Amount and it also lists it for sale in the same transaction — with a Destination too, only that one buyer can take it.
NFTokenCreateOfferLists one for sale, or bids on someone else’s. A sell offer may ask for nothing at all, which is how a gift is sent. A Destination locks the offer to a single account.
NFTokenAcceptOfferTakes an offer. Hand it a sell offer and a buy offer together and it settles both at once — a brokered sale, where the broker keeps an NFTokenBrokerFee and never holds the NFT.
NFTokenCancelOfferWithdraws offers you made. An offer left standing stays takeable, so cancel what you no longer mean.
NFTokenBurnDestroys the token and releases its share of the reserve. The owner may always burn their own; the issuer may burn one held by somebody else only if it was minted burnable.
NFTokenModifyChanges the link. Issuer only, mutable tokens only — see above.

The four flags are set once, at mint, and can never be added or removed afterwards.

FlagLeave it off and…Set it when
tfTransferableonly the issuer can ever buy or sell it — everyone else is refused outright.you want it traded at all. Royalties require it.
tfBurnableonly the owner can destroy it.you need to be able to destroy one you no longer control — a redeemed ticket, a revoked credential.
tfOnlyXRPit can be sold for any token on the ledger.you want every sale priced in XRP and nothing else.
tfMutablethe link is frozen for good, mistakes included.you want to be able to repair it later, knowing what that hands over.

One more field explains how most collections are actually made. An account can name another as its NFTokenMinter, and that account may then mint carrying an Issuer field pointing back at the first.

The NFT is issued by the creator; the transaction is sent, and paid for, by the marketplace. It also lets that marketplace burn or modify on the creator's behalf — a real delegation of authority, not a billing arrangement.

What getting it wrong looks like

Every line below is a real shape on the XRP Ledger today, with how many NFTs carry it. None of them failed to mint — the ledger accepts all of them without complaint, which is exactly why they are worth recognising before you send yours.

Written like thisNFTsWhat happens
https://yoursite.com/meta/1.json213,674Whoever runs the domain decides what the art is, forever. Let it expire and the NFT shows nothing.
https://ipfs.io/ipfs/bafy…242,954The file is safe, the address is not: it dies with that one gateway.
QmQr1RE4mm3fu8Pz2…80,753An identifier with no scheme in front of it. Every viewer has to guess it means IPFS, and some do not.
http://…8,656Not https. Browsers block insecure content on a secure page, so the art silently fails to load.
ipfs://ipfs/bafy…3,639Doubled prefix. Resolves to nothing unless the reader happens to strip it.
http://localhost:8080/1.json176A development machine. It resolved on the minter’s laptop and has never resolved anywhere else.
ar://<id>36Nothing on the XRP Ledger reads this prefix.
ipfs://null22A placeholder that went to mainnet.

And one that is not wrong, only dated: 585,962 NFTs use ipfs://Qm…, the older identifier format. It works. New collections should still prefer the bafy… form, which is what IPFS now recommends and what subdomain gateways need.

The single check that catches almost all of this: paste your own URI into a browser before you mint the collection, on a machine that is not the one you built it on.

If you use Arweave, do not write ar://

Arweave is the other content-addressed option, and a reasonable one: you pay once and the file is meant to stay for centuries. Its own documentation asks you to write links as ar://<id> rather than as a web address, so a link keeps working even if today's Arweave websites disappear. On the chains whose software understands that prefix, it is good advice.

The XRP Ledger is not one of them. No XRPL marketplace resolves the prefix, so an ar:// link has nothing behind it to fetch: 36 NFTs carry one, and not one of those checked has ever returned a picture.

Meanwhile 72,115 NFTs sit on Arweave quite happily by writing the same file as an ordinary address, https://arweave.net/<id>. The identifier in that path is Arweave's transaction id, derived from the data itself, so the bytes still cannot be swapped — it is the gateway trap above, not a plain web server.

Four ways a file that minted fine still goes missing

  • Public gateways refuse requests that look like a browser. ipfs.io, dweb.link and w3s.link all reject requests whose user-agent begins Mozilla/5.0, a rule aimed at scrapers. A file that looks dead to a script pretending to be Chrome is often alive to one that says nothing at all.
  • A gateway can answer "200 OK" and send a placeholder page. Judge success on what came back, never on the status code.
  • Pinning on your own gateway while linking to a public one. One collection kept its files on a private host but named a public gateway that had never held them: 2,291 NFTs read as permanently lost until the right host was tried.
  • Metadata naming an image nobody uploaded. The metadata file resolves, the link inside it does not. Fetching your own URI is not enough — follow it to the picture.

Related reading: how XLS-20 minting works and the metadata format in more detail.

Which method to choose

Every method above survives some kinds of neglect and not others, and the two questions that matter pull in different directions. The first is what happens if everyone walks away. The second is what stops the person who minted it changing the picture later.

MethodIf nobody maintains anythingIf the issuer wants it changed
ipfs:// on the NFTNothing to recover — the link is the file.Impossible. Nobody can, including you.
ipfs:// + tfMutableThe same.One signed transaction per NFT, on the ledger, where the holder can see it.
Issuer Domain → IPFS folderRecoverable: the folder is content-addressed and anyone can pin it.One transaction silently repoints the whole collection.
Gateway URL on the NFTThe address dies with the gateway, but the identifier is inside it and can be lifted out by hand.Impossible, same as the first row.
Issuer Domain → web APIGone. Nothing on the ledger links the token to a file, and nobody archives API answers.One transaction silently repoints the whole collection.
Plain web serverGone, and there was never anything to recover.Silently, at any moment, with no ledger event at all.

Only one option is strong in both columns, which is why it is the recommendation in step 4 above: put an ipfs:// link on the NFT and set tfMutable. The artwork is recoverable from the token alone, and the one person who can change it has to do so in public, one token at a time.

Leave tfMutable off only if you actively want the stronger promise that not even you can ever change it. That is a real position to take, and some collections take it deliberately — just take it knowing a mistake in the link is then permanent.

What tfMutable actually hands over

Worth understanding before you set it, because the article recommends it and it is not symmetrical. The transaction that does the changing is NFTokenModify, and the rules are in the server's own checks:

  • Only the issuer can send it — or a wallet the issuer has named as its authorised minter. The person holding the NFT cannot.
  • It carries an Owner field naming whoever holds the token today. That holder does not sign it and cannot refuse it.
  • It changes exactly one thing, the link. Send it with no link at all and the NFT is left with none.
  • It only works if tfMutable was set when the NFT was minted. Otherwise it fails, permanently, for that token.

So the flag is you keeping the right to change the picture on something somebody else paid for. What makes that defensible rather than alarming is that it happens one token at a time, in a signed transaction anyone can see — exactly what the issuer Domain methods above do not give you.

It is still a promise you are choosing not to make. A buyer who cares about permanence can read the flag off the token before buying.

Method

Every figure counts all 8,618,070 NFTs on the ledger on 2026-09-04 — the whole population, not a sample of it — classed by where the artwork lives rather than by how the link is spelled. A web address containing /ipfs/ or an identifier counts as IPFS, because the bytes it names cannot be swapped.

An NFT with no link counts as via issuer API or via issuer IPFS folder when its issuing account publishes a Domain, according to which of the two that Domain holds, and as nothing on-chain when it publishes none.

One collection, expo-2025-dwnft, is 5,251,612 NFTs on its own — 60.9% of every NFT on the ledger, all pointing at one web server. Percentages here set it aside, because including it describes that minter rather than the ledger: counted in, a plain web server holds 63.4% and the content-addressed rows 30.9%. Collection volumes are lifetime XRP traded.