Hands on guide

How to integrate IPFS in a Node.js or React app

Four production ready paths for adding IPFS storage to a JavaScript or TypeScript application — Pinata SDK, Storacha CLI and JS client, Filebase S3 compatible API, and the standardised IPFS Pinning Service API. Each path links back to the 8 active providers covered on this site so you can pick the one that fits your bill.

Pick an integration path

Before writing any code, decide which property matters most for your project: developer ergonomics, cost predictability, vendor neutrality, or trust minimisation. Each path below optimises for a different one of those.

PathOptimises forReference provider
Pinata SDKDeveloper ergonomics, fastest time to first uploadPinata
Storacha JS client / CLIUCAN delegation, Filecoin redundancy, open protocolStoracha
S3 compatible APIReusing AWS SDK code, hybrid object plus IPFS storageFilebase
IPFS Pinning Service APIVendor neutrality, swap providers without code changesFilebase, Pinata, Crust, others

Path 1 — managed SDK

Upload to IPFS from Node.js with Pinata

The Pinata SDK is the lowest friction option for a Next.js, React, or Node.js project. The example below mirrors the official quickstart. The JWT is treated as a secret — keep it in a server side environment variable, not in client side code.

// npm install pinata

import { PinataSDK } from "pinata";

const pinata = new PinataSDK({
  pinataJwt: process.env.PINATA_JWT!,
  pinataGateway: "example-gateway.mypinata.cloud",
});

async function uploadHello() {
  const file = new File(["hello world!"], "hello.txt", {
    type: "text/plain",
  });
  const upload = await pinata.upload.public.file(file);
  console.log(upload);
  // { cid: "bafkrei...", name: "hello.txt", size: 12, ... }
}

async function retrieve(cid: string) {
  const url = await pinata.gateways.convert(cid);
  console.log(url);
  // https://example-gateway.mypinata.cloud/ipfs/<cid>
}

For client side uploads, generate a presigned URL on the server using pinata.upload.public.createSignedURL and pass that to the browser. The browser POSTs the file to the signed URL — the long lived JWT never reaches the client.

Path 2 — open protocol + Filecoin redundancy

Upload via the Storacha JavaScript client

Storacha (formerly web3.storage) authenticates with UCAN delegations rather than long lived API keys. The CLI is the fastest way to try it; the JS client is the recommended path for production integration.

// Install the CLI globally, then log in and create a space.
// npm install -g @storacha/cli
// storacha login you@example.com
// storacha space create my-app

// Upload via the JS client:
// npm install @storacha/client

import { create } from "@storacha/client";

const client = await create();
// Authorise with an email or import a stored agent.

const space = await client.createSpace("my-app", {
  account: await client.login("you@example.com"),
});
await client.setCurrentSpace(space.did());

const files = [new File(["hello"], "hello.txt")];
const cid = await client.uploadDirectory(files);

console.log(`https://storacha.link/ipfs/${cid}/hello.txt`);

Storacha uploads are content addressed by CAR (Content Archive) files and replicated to Filecoin storage providers for durability. Retrieval goes through the storacha.link gateway by default but works from any IPFS gateway.

Path 3 — reuse the AWS SDK

Upload to IPFS through Filebase's S3 API

Filebase ships an S3 compatible endpoint at https://s3.filebase.com. Any AWS SDK or S3 CLI can talk to it; objects placed in an IPFS bucket are automatically pinned and addressable by CID through the Filebase gateway.

// npm install @aws-sdk/client-s3

import { S3Client, PutObjectCommand, HeadObjectCommand } from "@aws-sdk/client-s3";

const s3 = new S3Client({
  endpoint: "https://s3.filebase.com",
  region: "us-east-1",
  credentials: {
    accessKeyId: process.env.FILEBASE_KEY!,
    secretAccessKey: process.env.FILEBASE_SECRET!,
  },
});

await s3.send(
  new PutObjectCommand({
    Bucket: "my-ipfs-bucket",
    Key: "hello.txt",
    Body: Buffer.from("hello world!"),
    ContentType: "text/plain",
  }),
);

// The IPFS CID is returned in the x-amz-meta-cid metadata header.
const head = await s3.send(
  new HeadObjectCommand({ Bucket: "my-ipfs-bucket", Key: "hello.txt" }),
);
const cid = head.Metadata?.cid;
console.log(`https://ipfs.filebase.io/ipfs/${cid}`);

Path 4 — vendor neutral

Talk to any provider with the IPFS Pinning Service API

The IPFS Pinning Service API (PSA) is a Protocol Labs maintained REST spec. Filebase, Pinata, Crust, ipfs-cluster, and IPFS Desktop all speak it. Code written against the PSA can swap providers by changing the endpoint and token.

// Pin an existing CID through any IPFS Pinning Service API provider.

const endpoint = process.env.PIN_ENDPOINT!; // e.g. https://api.filebase.io/v1/ipfs/pins
const token = process.env.PIN_TOKEN!;

async function pin(cid: string, name: string) {
  const res = await fetch(`${endpoint}`, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${token}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ cid, name }),
  });
  if (!res.ok) throw new Error(`Pin failed: ${res.status} ${await res.text()}`);
  return (await res.json()) as { requestid: string; status: string };
}

console.log(
  await pin("bafkreidvbhs33ighmljlvr7zbv2ywwzcmp5adtf4kqvlly67cy56bdtmve", "hello.txt"),
);

Reference compliance reports for each provider are published at the ipfs-shipyard pinning service compliance dashboard.

After the upload

Retrieval, IPNS, and gateway patterns

Once a file is pinned, retrieval is just an HTTP GET against an IPFS gateway. The CID is the same on every gateway; pick the one with the best latency, the SLA you need, and the takedown policy your jurisdiction can live with.

  • Path style: https://gateway.example.com/ipfs/<cid>/path — works everywhere; subject to origin sharing.
  • Subdomain style: https://<cid>.ipfs.dweb.link/path — each CID gets its own origin, which helps with browser security model edge cases.
  • IPNS: for content that needs a stable name but changing CIDs (a static site, an app manifest), publish an IPNS name. Filebase, Storacha, and Lighthouse all support IPNS; consult the per provider page for the exact API.
  • Dedicated gateway: production traffic should route through your provider's dedicated gateway with a custom domain. This gives you analytics, access controls, CDN caching, and a predictable SLA. Pinata, Filebase, Fleek, QuickNode, and 4EVERLAND all ship dedicated gateways.

Operations

Things to verify before going live

  • The API key or token used by your server is scoped to write only the buckets or spaces you intend. Most providers support narrower scopes than the default admin key.
  • Storage and bandwidth allowances are set high enough for peak traffic plus a margin. Bandwidth overages are the most common source of surprise bills.
  • Retrieval works through both your dedicated gateway and at least one public fallback (ipfs.io or dweb.link). Public gateways will eventually return your CID once it propagates the DHT.
  • You have a content takedown policy. Public IPFS content is replicated outside your control; CIDs cannot be revoked. Sensitive content goes in a private IPFS bucket (Pinata) or stays off IPFS entirely.
  • For long term durability, layer a Filecoin backed provider on top of, or instead of, a pure hot pinning service. Storacha and Lighthouse both back their pins with Filecoin storage deals.

Pick a provider

See the full side by side comparison at /ipfs or jump to a specific provider:

Page maintained by Mudassir Khan · Verified 2026-06-02. Code examples mirror the providers' official quickstarts at the time of writing — confirm the latest API surface in the linked docs before shipping.