Querying with GraphQL
Transaction metadata can be queried using GraphQL. This includes both metadata automatically stored for each transaction and custom metadata you design yourself using our tags feature.
If you prefer learning by building a project, you may enjoy this step-by-step tutorial where you’ll learn how to setup a project, install the Apollo GraphQL libraries and then build a tool to search Arweave for recently uploaded image files.
Bundlr vs Arweave GraphQL
Bundlr GraphQL and Arweave GraphQL (opens in a new tab) both offer ways to query transaction metadata, however, they differ in several ways. Bundlr GraphQL requires you to connect to the node-specific endpoint where you posted your transaction, while Arweave GraphQL uses a universal endpoint for all queries. Bundlr GraphQL is cross-chain, it includes the address (regardless of chain) that posted the transaction, while Arweave GraphQL only includes Arweave addresses. Bundlr GraphQL also includes the currency used for payment, a receipt (if requested when uploading), and a true timestamp accurate to the millisecond of when the transaction was posted. Arweave GraphQL allows for querying by block structure (opens in a new tab), including block ID, block range, and block height, which Bundlr GraphQL does not support.
Bundlr GraphQL | Arweave GraphQL | |
---|---|---|
Endpoint | Node-specefic. Connect to the endpoint associated with the node where you posted your transaction. | Universal endpoint for all queries. |
Cross-chain | Yes. Includes the address (regardless of chain) that posted the transaction. | No. Includes Arweave addresses only. |
Original payment currency | Included. | Not included. |
Timestamp | Includes a timestamp accurate to the millisecond of when the transaction was posted, along with an (optional) cryptographically signed receipt. | Timestamp is based on block time, accurate to ~2 minutes. |
Blocks | Not included. | Included (opens in a new tab). You can query by block ID, block range, and block height. |
GraphQL clients
You can query using an HTTP library like fetch or axios. You can also use specialized clients like Apollo Client (opens in a new tab) or urql (opens in a new tab).
The next two sections detail first Bundlr GraphQL followed by Arweave GraphQL. While the two schemas are similar, there are differences you’ll need to be aware of when developing your projects. There is no one schema that is “better” than the other, the decision on which to use will depend on your own project and your specific needs.
Bundlr GraphQL
Anatomy of a query
A GraphQL query is made up of:
- Query Arguments: Arguments that specify search parameters, limit the number of results returned, or enable pagination.
- Results Fields: Fields that define the data you want to retrieve.

Query arguments
Any of the following query arguments can be used as search parameters:
Field | Description |
---|---|
ids | An array of transaction IDs passed as strings. Values are ORed together, matching results will include transactions that have any of the supplied IDs. |
owner | The address used when posting the transaction. Can be a native address from any of the chains supported by Bundlr. Note in results fields, this is referred to as address . |
currency | The currency used to pay for the transaction. |
tags | An array of tag name / value pairs passed as JSON objects. |
Results fields
When building a query, any of the following values be included in your results:
Field | Description |
---|---|
id | The transaction ID. |
address | The address used when posting the transaction. Can be a native address from any of the chains supported by Bundlr. Note in query arguements, this is referred to as owner . |
currency | The currency used to pay for the transaction. |
receipt {   deadlineHeight   signature   version } | An optional receipt, only exists if a user requested one at upload.deadlineHeight : The block number by which the transaction must be finalized on Arweave. signature : A signed deep hash of the JSON receipt. |
tags {   name   value } | An array of tags supplied as name / value pairs. Exists if the user added them at upload. |
timestamp | The timestamp, accurate to the millisecond of when the transaction was posted. In cases where there exists a receipt, this value will be the same as the receipt timestamp. |
Endpoints
Connect to the GraphQL endpoint associated with the node you uploaded your transaction to.
GraphQL sandbox
Clicking on any of the endpoint URLs above will direct you to the GraphQL Sandbox used for building and testing queries. Press Control+Space at any time to see an interactive popup window of either query arguments or results fields.

Sample queries
Queries return transaction metadata. To then retrieve data, use the returned transaction ID and download the data from a gateway using an URL formed as follows https://arweave.net/[transaction-id]
.
Transaction IDs
Search by transaction IDs.
query getByIds {
transactions(
ids: ["--52WQHJIJod_rni8pkl1Vxt9MFGoXZAm8SC7ex6C1o", "--52THRWpX_RJzGcNXmtQ2DSP37d1e1VQ4YmvbY5ZXo"]) {
edges {
node {
id
tags {
name
value
}
}
}
}
}
Timestamps
Search by timestamps.
query getByTimestamp {
transactions(timestamp: { from: 1688144401000, to: 1688317201000 }) {
edges {
node {
id
}
}
}
}
Bundlr timestamps are accurate to the millisecond, so you need to provide a timestamp in millisecond format. You can convert from human-readable time to UNIX timestamp using websites like Epoch101 (opens in a new tab), be sure to convert in millisecond format not second.
Owners
Search for transactions matching the wallet address used when posting the transaction.
query getByOwner {
transactions(
owners: ["0xBcb812C6e26F4F0F78Bd7B6222461FF24F2942AE", "0xaC568a981B1370B2e1bAA8cE30BD5AC9E28C572D"]) {
edges {
node {
id
address
}
}
}
}
Tags
Search for transactions matching tag name / value pairs.
query getAllPNGs {
transactions(tags: [{ name: "Content-Type", values: ["image/png"] }]) {
edges {
node {
id
address
}
}
}
}
Search for transactions matching the tag with name Content-Type and the values of image/png OR image/jpg.
query getTagsWithOR {
transactions(tags: [{ name: "Content-Type", values: ["image/png", "image/jpg"] }]) {
edges {
node {
tags {
name
value
}
}
}
}
}
Search for transactions matching the tag with name Content-Type and the values of image/png AND image/jpg.
query getTagsWithAnd {
transactions(
tags: [
{ name: "Content-Type", values: ["image/jpg"] }
{ name: "Content-Type", values: ["image/png"] }
]
) {
edges {
node {
tags {
name
value
}
}
}
}
}
Limiting results
Limit the number of results returned by including the limit
parameter.
query getAllPNGs {
transactions(
limit: 10
tags: [{ name: "Content-Type", values: ["image/png"] }]
) {
edges {
node {
id
address
}
}
}
}
Pagination
You can request a maximum of 100 results returned from each query, to obtain additional results use pagination.
When using pagination you:
- Retrieve the
cursor
field, this acts like a bookmark in the search results you can then return to. - Use saved
cursor
value to obtain subsequent search results.
The following query returns 10 transactions tagged image/png
occurring after the cursor with value: LS02d1NsM3R6aUprd3dKUzVjN1FXaWg5aUxsbXh5dVJJbGlydHJtNlpPbw
. To then obtain the next 10 transactions, use the final cursor
value returned from this query as the value of the after
parameter in the following query.
query getPNGs {
transactions(
limit: 10
tags: [{ name: "Content-Type", values: ["image/png"] }]
after: "LS02d1NsM3R6aUprd3dKUzVjN1FXaWg5aUxsbXh5dVJJbGlydHJtNlpPbw"
) {
edges {
node {
id
}
cursor
}
}
}
Sorting
You can sort results by timestamp in either ascending or descending order using the order
field.
query getAllByOwnerAsc {
transactions(
owners: ["0xBcb812C6e26F4F0F78Bd7B6222461FF24F2942AE"]
order: ASC
) {
edges {
node {
id
address
}
}
}
}
query getAllByOwnerDesc {
transactions(
owners: ["0xBcb812C6e26F4F0F78Bd7B6222461FF24F2942AE"]
order: DESC
) {
edges {
node {
id
address
}
}
}
}
Arweave GraphQL
Anatomy of a query
A GraphQL query is made up of:
- Query Arguments: Arguments that specify search parameters, limit the number of results returned, or enable pagination.
- Results Fields: Fields that define the data you want to retrieve.

Query arguments
Any of the following query arguments can be used as search parameters:
Field | Description |
---|---|
ids | An array of transaction IDs passed as strings. Values are ORed together, matching results will include transactions that have any of the supplied IDs. |
owner | The Arweave address used when posting the transaction. Note if you post to Bundlr using a non-Arweave wallet address, it will be converted into an Arweave-like address and stored in this field. There is no way to retrieve eth or sol addresses from Arweave GraphQL, you must use Bundlr GraphQL. |
recipients | The currency used to pay for the transaction. |
bundledIn | Transaction ID of the parent bundle for this transaction. Transaction ID can be of a nested bundle or a regular bundle. |
block | Details specific to a transaction's block. |
tags | An array of tag name / value pairs passed as JSON objects. Values are ORed together, matching results will include transactions matching any of the supplied tags. |
Results fields
When building a query, you can request any of the following values be included in your results:
Field | Description |
---|---|
id | The transaction ID. |
anchor | A value used to prevent against double spends. |
signature | The signature used to sign the transaction. |
recipient | Address of the account the tx was sent to (use for fund transfers). |
owner | The Arweave address used when posting the transaction. Note if you post to Bundlr using a non-Arweave wallet address, it will be converted into an Arweave-like address and stored in this field. There is no way to retrieve eth or sol addresses from Arweave GraphQL, you must use Bundlr GraphQL. |
fee {   winston   ar } | The transaction mining fee. |
quantity {   winston   ar } | The amount paid for the transaction. |
data {   size   type } | The size and type of the data payload. |
tags | An array of tags supplied as name / value pairs. Exists if the user added them at upload. |
block {   id   timestamp   height   previous } | Details specific to a transaction's block, including block number, mining date, block hash, and the previous block hash. |
bundledIn | Transaction ID of the parent bundle for this transaction. Transaction ID can be of a nested bundle or a regular bundle. |
Endpoints
Arweave offers a universal endpoint, you do not need to pick an endpoint associated with the node you uploaded to. The three endpoints below all provide access to the same dataset, use the one with the fastest response times.
- https://arweave.net/graphql (opens in a new tab)
- https://arweave.dev/graphql (opens in a new tab)
- https://arweave-search.goldsky.com/graphql (opens in a new tab)
GraphQL playground
Clicking on any of the endpoint URLs will direct you to the GraphQL Playground used for building and testing queries. Press Control+Space at any time to see an interactive popup window of either query arguments or results fields.

Sample queries
Queries return transaction metadata. To then retrieve data, use the returned transaction ID and download the data from a gateway using an URL formed as follows https://arweave.net/[transaction-id]
.
Transaction IDs
Search by transaction IDs.
query getByIds {
transactions(ids: ["1t-Z0oDxQLvACpLXUwwfbplw7vHialWH8mkNAvzTkDw", "1w6PBHQ5e0hMJWsfRCJr66JvQAcyws0k4D97kG4GVm8"]) {
edges {
node {
id
tags {
name
value
}
}
}
}
}
Owners
Search for transactions matching the Arweave wallet address used when posting the transaction.
query getByOwners {
transactions(owners: ["M6w588ZkR8SVFdPkNXdBy4sqbMN0Y3F8ZJUWm2WCm8M"]) {
edges {
node {
id
}
}
}
}
Tags
Search for transactions matching tag name / value pairs.
query getAllPNGs {
transactions(tags: { name: "Content-Type", values: ["image/png"] }) {
edges {
node {
id
}
}
}
}
Limiting results
Limit the number of results returned by including the first
parameter.
query get10Pngs {
transactions(
first: 10
tags: { name: "Content-Type", values: ["image/png"] }
) {
edges {
node {
id
}
}
}
}
Pagination
You can request a maximum of 100 results returned from each query, to obtain additional results use pagination.
When using pagination you must:
- Retrieve the cursor field, this acts like a bookmark in the search results you can then return to.
- Use saved cursor values to obtain subsequent search results.
The following query returns 10 transactions tagged image/png
occurring after the cursor with value LS02d1NsM3R6aUprd3dKUzVjN1FXaWg5aUxsbXh5dVJJbGlydHJtNlpPbw
. To then obtain the next 10 transactions, use the final cursor
value returned from this query as the value of the after
parameter in the following query.
query getPNGs {
transactions(
first: 10
tags: [{ name: "Content-Type", values: ["image/png"] }]
after: "LS02d1NsM3R6aUprd3dKUzVjN1FXaWg5aUxsbXh5dVJJbGlydHJtNlpPbw"
) {
edges {
node {
id
}
cursor
}
}
}
Sorting
You can sort results by block height in either ascending or descending order using the sort
parameter.
query getByOwnersAsc {
transactions(
owners: ["M6w588ZkR8SVFdPkNXdBy4sqbMN0Y3F8ZJUWm2WCm8M"]
sort: HEIGHT_ASC
) {
edges {
node {
id
}
}
}
}
query getByOwnersDesc {
transactions(
owners: ["M6w588ZkR8SVFdPkNXdBy4sqbMN0Y3F8ZJUWm2WCm8M"]
sort: HEIGHT_DESC
) {
edges {
node {
id
}
}
}
}
Further reading
Additional information on Arweave GraphQL can be found on their website (opens in a new tab).