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:
- Find - Query GraphQL to discover transactions by tags, metadata, owner, or other criteria
- 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:
- Navigate to https://arweave.net/graphql in your browser
- Enter your GraphQL query in the interface
- 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 withafter
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
Fetch Data via REST API
Learn how to retrieve the actual data using transaction IDs.
Run Your Own Gateway
Set up a gateway to index and serve your specific data.
Upload Data with Turbo
Start uploading your data to Arweave's permanent storage.
Use Wayfinder for Smart Routing
Automatically route requests to the best performing gateway.
How is this guide?