GraphQL Cursor Decoder
GraphQL Relay connections encode pagination cursors as Base64. The most common format is arrayconnection:<index> — so YXJyYXljb25uZWN0aW9uOjU= decodes to arrayconnection:5. Paste a cursor (from edges[].cursor, pageInfo.endCursor, or an after: argument) to decode it, or build one. Runs locally; nothing is uploaded.
How to decode a GraphQL cursor
A Relay cursor is just a Base64 string. Copy one from edges[].cursor, pageInfo.startCursor/pageInfo.endCursor, or an after:/before: argument, and paste it into the box above. The tool Base64-decodes it locally and shows the underlying value. In the vast majority of Relay APIs that value is arrayconnection:<index>. To go the other way and mint a cursor, toggle the button to Encode.
What is a Relay cursor?
A cursor is an opaque Base64 string that identifies a position in a connection. It comes from the Relay Cursor Connections spec, where every edge carries a cursor and the connection exposes pageInfo.startCursor and pageInfo.endCursor. You page through results by passing a cursor back to the server with the first/after arguments (forward) or last/before (backward). "Opaque" means you are not supposed to parse it — but because it is only Base64, you can.
The arrayconnection:N format
Nearly every Relay cursor you will ever see decodes to arrayconnection:<index>. That is because the reference library graphql-relay-js ships a cursorForObjectInConnection helper that Base64-encodes the literal string arrayconnection:<index>, where the number is the item's zero-based offset in the connection array. So arrayconnection:5 points at the sixth item. It is a convenience default, not a rule of the spec — but so many servers use graphql-relay-js unchanged that this format is effectively ubiquitous.
Custom cursor formats
Servers are free to put anything inside a cursor. Some encode a record id, some a small JSON payload (for keyset/seek pagination), and some a timestamp. When this tool finds JSON inside a cursor it pretty-prints it; otherwise it shows the raw decoded value so you can see whatever the server chose to stash there.
Are cursors secret?
No. Cursors are opaque, not encrypted or signed — they are plain Base64, so anyone can decode or forge one. Never trust a cursor as authorization and never assume a client cannot see or tamper with its contents. If a position needs to be tamper-proof, the server must sign or validate it; the cursor value alone proves nothing.
Is this private?
Yes. Decoding and encoding run fully in the browser with JavaScript — your cursor is processed locally and nothing is uploaded to any server. You can confirm in DevTools → Network: decoding a cursor fires no request.
Frequently asked questions
How do I decode a GraphQL/Relay cursor?
Paste the cursor from edges[].cursor, pageInfo.endCursor, or an after: argument into the input above. The tool Base64-decodes it locally and shows the underlying value — most commonly arrayconnection:<index>.
Why does my cursor decode to 'arrayconnection:5'?
That is the default format from graphql-relay-js. Its cursorForObjectInConnection helper Base64-encodes arrayconnection:<index>, where the number is the item's zero-based offset in the connection. So arrayconnection:5 is the sixth item.
Are GraphQL cursors encrypted or secure?
No — they are opaque Base64, which is trivially decoded and forged. Do not use a cursor as authorization or trust its contents as verified.
How do I create a cursor?
Switch the tool to Encode mode and type the value you want to wrap, for example arrayconnection:5. It is Base64-encoded into a cursor you can drop into an after: or before: argument.
My cursor decodes to gibberish/JSON — why?
Not every server uses the Relay array-connection format. Some use a custom, server-defined format — a record id, a JSON payload, or a timestamp. This tool pretty-prints JSON when it finds it and otherwise shows the raw decoded value.
Need plain Base64 encode/decode?
The main base64.dev tool handles text, files, and URL-safe mode with auto-detect.
Open base64.dev →