With Pinata, there are a few ways you can pin files to IPFS!

HTML uploads are currently only available on paid plans with granted access. If you are on a paid plan and wish to upload HTML please send a request through our support chat or send an email to [email protected]

API & SDKs

If you’re a developer that needs to build decentralized applications, then you will likely want to use the SDK or the Pinata API. These make it simple to integrate IPFS uploads into your App!

Using the SDK

The Pinata SDK is able to handle mutliple kinds of uploads, whether its file objects, base64 strings, or even content from remote URLs.

import { PinataSDK } from "pinata-web3";

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

const file = new File(["hello"], "Testing.txt", { type: "text/plain" });
const upload = await pinata.upload.file(file);

The SDK is also equipped to handle an array of file objects.

import { PinataSDK } from "pinata-web3";

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

const file1 = new File(["hello world!"], "hello.txt", { type: "text/plain" })
const file2 = new File(["hello world again!"], "hello2.txt", { type: "text/plain" })
const upload = await pinata.upload.fileArray([file1, file2])

Using the API

The API is a bit more flexible, as it can be used in multiple languages or environments, and is sometimes preferred for client side uploads. With that, we should express warning in that client side applications will expose API keys.

Using your API Keys in a client side application will expose them! Consider using a signed JWT approach.

The API accepts File objects (and blobs in the right environment) through a multipart form data request, where the object has a key of file. Additionally you can add pinataMetadata and pinataOptions to the request. Here is an example of how you could upload with the API:

const JWT = "YOUR_PINATA_JWT";

async function pinFileToIPFS() {
  try {
    const formData = new FormData();

    const file = new File(["hello"], "Testing.txt", { type: "text/plain" });
    formData.append("file", file);

    const pinataMetadata = JSON.stringify({
      name: "File name",
    });
    formData.append("pinataMetadata", pinataMetadata);

    const pinataOptions = JSON.stringify({
      cidVersion: 1,
    });
    formData.append("pinataOptions", pinataOptions);

    const request = await fetch("https://api.pinata.cloud/pinning/pinFileToIPFS", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${JWT}`
      },
      body: formData,
    });
    const response = await request.json();
    console.log(response);
  } catch (error) {
    console.log(error);
  }
}

Common File Recipes

Below are some common recipes for uploading a file.

Blob

Usually you can pass a Blob directly into the request but to help guarantee success we recommend passing it into a File object.

Blob
import { PinataSDK } from "pinata-web3";

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

const text = "Hello World!";
const blob = new Blob([text], { type: "text/plain" });
const file = new File(["hello world!"], "hello.txt", { type: "text/plain" })
const upload = await pinata.upload.file(file)

JSON

Pinata makes it easy to upload JSON objects using the json method.

JSON
import { PinataSDK } from "pinata-web3";

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

const upload = await pinata.upload.json({
  name: "Pinnie NFT",
  description: "A Pinnie NFT from Pinata",
  image: "ipfs://bafkreih5aznjvttude6c3wbvqeebb6rlx5wkbzyppv7garjiubll2ceym4"
})

Local Files

If you need to upload files from a local file source you can use fs to feed a file into a blob, then turn that blob into a File.

const { PinataSDK } = require("pinata-web3")
const fs = require("fs")
const { Blob } = require("buffer")

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

const blob = new Blob([fs.readFileSync("./hello-world.txt")]);
const file = new File([blob], "hello-world.txt", { type: "text/plain"})
const upload = await pinata.upload.file(file);

URL

To upload a file from an external URL you can stream the contents into an arrayBuffer, which then gets passed into a new Blob that can then be uploaded to Pinata. This has been abstracted in the SDK using the url method.

URL
import { PinataSDK } from "pinata-web3";

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

const upload = await pinata.upload.url("https://i.imgur.com/u4mGk5b.gif")

base64

To upload a file in base64 simply turn the contents into a buffer that is passed into a Blob. Alternatively you can use the SDK for this as well using the base64 method.

base64
import { PinataSDK } from "pinata-web3";

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

const upload = await pinata.upload.base64("SGVsbG8gV29ybGQh")

Folders

The SDK can accept an array of files using the fileArray method. Folders can also be uploaded via the API by creating an array of files and mapping over them to add them to the form data. This is different then having a single file entry and having multiple files for that one entry, which does not work.


We also have other tools like the Pinata CLI or Next.js Starter which can be used to upload using API Keys!

Web App

If you’re non-technical, you can use Pinata App to upload files, perfect if you just want to get started with NFTs and IPFS! It’s as simple as clicking the “Upload” button in the top right corner of the files page. Select your file, give it a name, then upload. Once it’s complete you’ll see it listed in the files page.

Start uploading by signing up for a free account!

Pin by CID

Another way you can upload content to Pinata is by transferring content that is already on IPFS. This could be CIDs that are on your own local IPFS node or another IPFS pinning service! You can do this with the “Pin by CID” button in the web app, like so:

Or you can pin by CID with the SDK using the cid method.

import { PinataSDK } from "pinata-web3";

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

const pin = await pinata.upload.cid("QmVLwvmGehsrNEvhcCnnsw5RQNseohgEkFNN1848zNzdng")

This will result in a request_id and Pinata will start looking for the file. Progress can be checked by using the pinJobs method.

import { PinataSDK } from "pinata-web3";

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

const jobs = await pinata.pinJobs().status("prechecking")

All possible filters are included in the API reference below, but these are the possible “status” filters:

status
string

Filter by the status of the job in the pinning queue (see potential statuses below)

  • prechecking Pinata is running preliminary validations on your pin request.
  • searching Pinata is actively searching for your content on the IPFS network. This may take some time if your content is isolated.
  • retrieving Pinata has located your content and is now in the process of retrieving it.
  • expired Pinata wasn’t able to find your content after a day of searching the IPFS network. Please make sure your content is hosted on the IPFS network before trying to pin again.
  • over_free_limit Pinning this object would put you over the free tier limit. Please add a credit card to continue pinning content.
  • over_max_size This object is too large of an item to pin. If you’re seeing this, please contact us for a more custom solution.
  • invalid_object The object you’re attempting to pin isn’t readable by IPFS nodes. Please contact us if you receive this, as we’d like to better understand what you’re attempting to pin.
  • bad_host_node You provided a host node that was either invalid or unreachable. Please make sure all provided host nodes are online and reachable.

Predetermining the CID

If you find yourself in a position where you want to pre-determine the CID before uploading you can use the multiformats library. The key is making sure you use raw codec and use blobs just like the Pinata API accepts to get the same results.

import { CID } from 'multiformats/cid'
import * as raw from 'multiformats/codecs/raw'
import { sha256 } from 'multiformats/hashes/sha2'
const JWT = "YOUR_PINATA_JWT"

async function main(){
  try {
    const text = "Hello World!";
    const blob = new Blob([text], { type: "text/plain" });
    const unit8array = new Uint8Array(await blob.arrayBuffer());
    const bytes = raw.encode(unit8array)
    const hash = await sha256.digest(bytes)
    const cid = CID.create(1, raw.code, hash)
     console.log(cid.toString())
  } catch(error) {
    console.log(error)
  }
}

async function pinFileToIPFS() {
  try {
    const text = "Hello World!";
    const blob = new Blob([text], { type: "text/plain" });
    const data = new FormData();
    data.append("file", blob);
    const options = JSON.stringify({
      cidVersion: 1
    })
    data.append("pinataOptions", options)

    const res = await fetch("https://api.pinata.cloud/pinning/pinFileToIPFS", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${JWT}`,
      },
      body: data
    });
    const resData = await res.json();
    console.log(resData.IpfsHash);
  } catch (error) {
    console.log(error);
  }
};

main()
pinFileToIPFS()