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:

FAQ

Frequently asked questions

What is the easiest way to upload to IPFS from JavaScript?

The Pinata SDK is the lowest friction path for a Node.js or React app. Install pinata from npm, pass your JWT, call pinata.upload.public.file(file), and you get back a CID. Storacha offers a similar developer experience through the @storacha/client package with UCAN delegation. Filebase exposes its IPFS layer through an S3 compatible API, which lets you reuse AWS SDK code unchanged.

What is the IPFS Pinning Service API?

The IPFS Pinning Service API (PSA) is a standardized REST API defined by Protocol Labs. Pinata, Filebase, Crust, and the IPFS CLI all support it. Code written against the PSA can talk to any compliant provider without changes, which is the safest hedge against future vendor lock in.

Should I upload from the browser or from my backend?

Upload from the backend whenever possible, so the IPFS API key never reaches the browser. When you do need browser uploads, use presigned URLs (Pinata, Filebase) or short lived UCAN delegations (Storacha) so the long lived key stays on the server. Never embed an admin JWT in client side code.

How do I make sure files stay pinned long term?

Pinned files stay pinned as long as your account is active and within the plan's storage allowance. For genuine long term durability beyond a single vendor, layer a Filecoin backed provider (Storacha or Lighthouse) on top of, or instead of, a pure hot pinning service. Crust Network adds on chain proofs of storage as a third option for trust minimised persistence.

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.