Encode and decode opaque pagination cursors
Turn a sort position into a URL-safe cursor string and validate it when it comes back from the client.
- JavaScript
- GreenSnippets
- MIT
- Executed with Node.js 22
function encodeCursor(position) {
return Buffer.from(JSON.stringify(position), "utf8").toString("base64url");
}
function decodeCursor(cursor) {
try {
const value = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
const valid =
value && typeof value === "object" && typeof value.id === "string" && typeof value.createdAt === "string";
return valid ? { id: value.id, createdAt: value.createdAt } : null;
} catch {
return null;
}
}Example / expected output
const next = encodeCursor({ id: "42", createdAt: "2025-01-01T00:00:00Z" });
decodeCursor(next); // { id: "42", createdAt: "2025-01-01T00:00:00Z" }How it works
Opaque cursors let you change the pagination internals later and discourage clients from building them by hand. The cursor is base64url JSON of the last item's sort keys. Always treat a returned cursor as untrusted input: decode defensively, validate the fields and return null for anything malformed.
Related snippets
- JavaScript Tested
Parse the Link header for pagination
Extract next, prev, first and last page URLs from an RFC 8288 Link header like GitHub's API returns.
- PHP Tested
Validate emails and URLs in PHP
Use filter_var to validate email addresses and http(s) URLs, with an allow-list for schemes.
- Python Tested
Sign API requests with HMAC-SHA256
Create and verify a timestamped signature over the method, path and body so requests cannot be forged or replayed.
- JavaScript Tested
Generate secure random IDs and integers
Create UUIDs, random integers in a range and URL-safe tokens with the Web Crypto API instead of Math.random.

