AR.IO LogoAR.IO Documentation

Find Data (via GraphQL)

Use GraphQL to find and identify Arweave data with powerful search and filtering capabilities. GraphQL is used for discovery - you query to get transaction IDs, then use those IDs to fetch the actual data.

GraphQL is for Discovery, Not Direct Access GraphQL finds data, it doesn't access it directly. Use GraphQL to get transaction IDs, then use those IDs with the REST API to fetch the actual data.

How GraphQL Works

GraphQL on Arweave follows a two-step process:

  1. Find - Query GraphQL to discover transactions by tags, metadata, owner, or other criteria
  2. Fetch - Use the transaction IDs from your query results to retrieve the actual data via the REST API

This separation allows for powerful data discovery while keeping data retrieval fast and efficient.

GraphQL Providers

  • arweave.net - https://arweave.net/graphql - Comprehensive indexing of all Arweave data
  • Goldsky - https://arweave-search.goldsky.com/graphql - High-performance GraphQL service with full data coverage

AR.IO Gateways: AR.IO gateways support the /graphql endpoint, but they only return data they've indexed. If you're uploading data and want it unbundled and indexed, you can run a gateway and configure it to unbundle your data, or post data items/bundles via the gateway's APIs (recommended). Learn more.

Quick Start

The easiest way to get started is using the interactive GraphQL playground:

  1. Navigate to https://arweave.net/graphql in your browser
  2. Enter your GraphQL query in the interface
  3. Press the "play" button to execute and see results

Basic Query Structure

Try this example query in the playground - it fetches the most recent 10 HTML pages from "MyApp":

query {
  transactions(
    tags: [
      { name: "Content-Type", values: ["text/html"] }
      { name: "App-Name", values: ["MyApp"] }
    ]
    sort: HEIGHT_DESC
    first: 10
  ) {
    edges {
      node {
        id
        tags {
          name
          value
        }
        data {
          size
        }
      }
    }
  }
}

Example Queries

Here's how to find videos using GraphQL:

const query = `
  query {
    transactions(
      tags: [{ name: "Content-Type", values: ["video/mp4"] }]
      first: 10
    ) {
      edges {
        node {
          id
          tags {
            name
            value
          }
          data {
            size
          }
        }
      }
    }
  }
`;

const response = await fetch("https://arweave.net/graphql", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ query }),
});

const data = await response.json();
const videos = data.data.transactions.edges;

// This returns transaction IDs that you can use with HTTP requests
console.log(
  "Found video IDs:",
  videos.map((v) => v.node.id)
);
const query = `
  query {
    transactions(owners: ["your-wallet-address"], first: 10) {
      edges {
        node {
          id
          tags {
            name
            value
          }
        }
      }
    }
  }
`;

const response = await fetch("https://arweave.net/graphql", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ query }),
});

const data = await response.json();
const transactions = data.data.transactions.edges;
console.log("Found transactions:", transactions.map(t => t.node.id));
const query = `
  query {
    transactions(block: { min: 1000000, max: 1100000 }, first: 10) {
      edges {
        node {
          id
          block {
            height
          }
        }
      }
    }
  }
`;

const response = await fetch("https://arweave.net/graphql", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ query }),
});

const data = await response.json();
const transactions = data.data.transactions.edges;
console.log("Found transactions in block range:", transactions.map(t => ({ id: t.node.id, height: t.node.block.height })));
// First page
const query = `
  query {
    transactions(
      tags: [{ name: "App-Name", values: ["MyApp"] }]
      first: 10
    ) {
      pageInfo {
        hasNextPage
      }
      edges {
        cursor
        node {
          id
          tags {
            name
            value
          }
        }
      }
    }
  }
`;

const response = await fetch("https://arweave.net/graphql", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ query }),
});

const data = await response.json();
const { edges, pageInfo } = data.data.transactions;

// Next page using cursor
if (pageInfo.hasNextPage) {
  const nextQuery = `
    query($cursor: String) {
      transactions(
        tags: [{ name: "App-Name", values: ["MyApp"] }]
        after: $cursor
        first: 10
      ) {
        pageInfo {
          hasNextPage
        }
        edges {
          cursor
          node {
            id
            tags {
              name
              value
            }
          }
        }
      }
    }
  `;

  const nextResponse = await fetch("https://arweave.net/graphql", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      query: nextQuery,
      variables: { cursor: edges[edges.length - 1].cursor },
    }),
  });

  const nextData = await nextResponse.json();
  console.log(nextData.data);
}

Pagination

As of September 2025, GraphQL endpoints have different limits:

  • arweave.net: Supports queries up to 1,000 items at once
  • Goldsky: Supports queries up to 100 items at once

For larger datasets, use cursor-based pagination to navigate through results.

How Pagination Works:

  • Use first parameter to specify page size (max 1,000 for arweave.net, max 100 for Goldsky)
  • Use pageInfo.hasNextPage to check if more results exist
  • Use cursor from the last item with after parameter for the next page
let allTransactions = [];
let hasNextPage = true;
let cursor = null;

while (hasNextPage) {
  const query = `
    query($cursor: String) {
      transactions(
        tags: [{ name: "App-Name", values: ["MyApp"] }]
        first: 100
        ${cursor ? "after: $cursor" : ""}
      ) {
        pageInfo {
          hasNextPage
        }
        edges {
          cursor
          node {
            id
            tags {
              name
              value
            }
          }
        }
      }
    }
  `;

  const response = await fetch("https://arweave.net/graphql", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      query,
      variables: cursor ? { cursor } : {},
    }),
  });

  const data = await response.json();
  const { edges, pageInfo } = data.data.transactions;

  allTransactions.push(...edges);
  hasNextPage = pageInfo.hasNextPage;
  cursor = edges.length > 0 ? edges[edges.length - 1].cursor : null;

  console.log(
    `Loaded ${edges.length} transactions. Total: ${allTransactions.length}`
  );
}

console.log(`Found ${allTransactions.length} total transactions`);

Query Optimization Tips

Follow these guidelines for optimal performance:

Specificity:

  • Use the most precise tags possible to narrow search scope
  • Query with essential tags only to reduce processing time

Schema Design:

  • Design your app's schema to reflect query patterns
  • Use tags that encapsulate frequent combinations of criteria

Include Non-tag Fields:

  • Add fields like owner to refine your search
  • This makes queries more efficient and targeted

Order Your Tags:

  • Arrange tags from most specific to most general
  • This leverages Arweave's indexing more effectively

Example Optimized Query:

// Well-optimized query with specific tags and useful fields
const query = `
  query {
    transactions(
      tags: [
        { name: "App-Name", values: ["MyApp"] }
        { name: "Content-Type", values: ["application/json"] }
        { name: "Version", values: ["1.0"] }
      ]
      owners: ["your-wallet-address"]
      first: 20
    ) {
      edges {
        node {
          id
          data {
            size
            type
          }
          tags {
            name
            value
          }
          block {
            height
            timestamp
          }
          owner {
            address
          }
        }
      }
    }
  }
`;

Next Steps

How is this guide?