rozod
    Preparing search index...

    rozod

    RoZod

    Type-safe Roblox API and OpenCloud client for TypeScript

    npm bundle size npm npm

    AboutFeaturesInstallationQuick StartUsageOpenCloudCreditsDocumentation


    RoZod makes working with Roblox APIs simple and type-safe in TypeScript. With 650+ classic Roblox web API endpoints and 95+ OpenCloud endpoints (all code-generated from official Roblox documentation), you get comprehensive coverage of virtually every available Roblox API with full type safety.

    Perfect for everything from small one-time NodeJS/Bun/Deno scripts to large-scale production applications. RoZod powers RoGold, a browser extension with 800,000+ active users, handling millions of API requests daily across both frontend extensions and backend workflows.

    • Simple Interface - Easy to understand API with minimal boilerplate
    • 🔒 Type Safety - Complete TypeScript type safety for requests and responses
    • 📚 750+ Total Endpoints - 650+ classic web APIs + 95+ OpenCloud APIs, all code-generated from official docs
    • 🚀 Production Ready - Battle-tested in applications serving 800,000+ users
    • 🔄 Pagination Helpers - Easy tools for handling paginated responses
    • 🔁 Batch Processing - Split large requests automatically to avoid API limits
    • 🌐 Universal Runtime Support - Works seamlessly in NodeJS, Bun, Deno, and browsers
    • 🔍 Custom Endpoints - Define your own endpoints with full type safety
    • 🧩 Smart Error Handling - Choose between safe unions or throw-on-error
    npm install rozod
    # or
    yarn add rozod
    # or
    pnpm add rozod
    import { fetchApi } from 'rozod';
    import { getUsersUserdetails } from 'rozod/lib/endpoints/usersv1';

    // Fetch user details with full type safety
    const userInfo = await fetchApi(getUsersUserdetails, { userIds: [1, 123456] });
    if (isAnyErrorResponse(userInfo)) {
    return;
    }
    console.log(userInfo.data[0].displayName); // Properly typed!
    import { fetchApi } from 'rozod';
    import { getGamesIcons } from 'rozod/lib/endpoints/gamesv1';

    const response = await fetchApi(getGamesIcons, { universeIds: [1534453623, 65241] });
    console.log(response.data);
    import { fetchApiPages } from 'rozod';
    import { getGroupsGroupidWallPosts } from 'rozod/lib/endpoints/groupsv2';

    // Automatically fetches all pages
    const allPosts = await fetchApiPages(getGroupsGroupidWallPosts, { groupId: 11479637 });
    console.log(`Found ${allPosts.length} wall posts`);
    import { fetchApiPagesGenerator } from 'rozod';
    import { getGroupsGroupidWallPosts } from 'rozod/lib/endpoints/groupsv2';

    // Process pages as they arrive
    const pages = fetchApiPagesGenerator(getGroupsGroupidWallPosts, { groupId: 11479637 });
    for await (const page of pages) {
    console.log(`Processing page with ${page.data.length} posts`);
    // Do something with this page
    }
    import { fetchApiSplit } from 'rozod';
    import { getGamesIcons } from 'rozod/lib/endpoints/gamesv1';

    // Will automatically split into smaller batches of 100 universeIds per request
    const data = await fetchApiSplit(
    getGamesIcons,
    { universeIds: [1, 2, 3, 4, 5 /* many more IDs */] },
    { universeIds: 100 },
    );
    console.log(data);

    By default, requests return either the success type or a simple AnyError. Use the tiny helper to check:

    import { fetchApi, isAnyErrorResponse } from 'rozod';
    import { getGamesIcons } from 'rozod/lib/endpoints/gamesv1';

    const res = await fetchApi(getGamesIcons, { universeIds: [1534453623] });
    if (isAnyErrorResponse(res)) {
    console.error(res.message);
    } else {
    console.log(res.data);
    }

    Prefer a straight try/catch? Enable throwing:

    try {
    const res = await fetchApi(getGamesIcons, { universeIds: [1534453623] }, { throwOnError: true });
    console.log(res.data);
    } catch (err) {
    console.error((err as Error).message);
    }

    Need the raw Response? Use returnRaw: true:

    const resp = await fetchApi(getGamesIcons, { universeIds: [1534453623] }, { returnRaw: true });
    const json = await resp.json();

    RoZod supports Roblox's newer OpenCloud APIs with the same easy interface:

    import { fetchApi } from 'rozod';
    import { v2 } from 'rozod/lib/opencloud';

    // Get universe details through OpenCloud
    const universeInfo = await fetchApi(v2.getCloudV2UniversesUniverseId, {
    universe_id: '123456789',
    });

    // Access typed properties
    console.log(universeInfo.displayName);
    console.log(universeInfo.description);
    import { fetchApi } from 'rozod';
    import { getCloudV2UniversesUniverseIdDataStoresDataStoreIdEntries } from 'rozod/lib/opencloud/v2/cloud';

    // Get DataStore entries with type safety
    const dataStoreEntries = await fetchApi(getCloudV2UniversesUniverseIdDataStoresDataStoreIdEntries, {
    universe_id: '123456789',
    data_store_id: 'MyStore',
    });

    RoZod handles Roblox authentication automatically with comprehensive security features:

    In browsers, authentication works automatically when users are logged into Roblox:

    import { fetchApi } from 'rozod';
    import { getUsersUserdetails } from 'rozod/lib/endpoints/usersv1';

    // Cookies are sent automatically - no setup required!
    const userInfo = await fetchApi(getUsersUserdetails, { userIds: [123456] });

    For server environments, you need to provide the .ROBLOSECURITY cookie manually:

    import { fetchApi } from 'rozod';
    import { getUsersUserdetails } from 'rozod/lib/endpoints/usersv1';

    const userInfo = await fetchApi(
    getUsersUserdetails,
    { userIds: [123456] },
    {
    headers: {
    'Cookie': '.ROBLOSECURITY=your_cookie_here'
    }
    }
    );

    RoZod automatically handles advanced Roblox security requirements:

    • ✅ XCSRF Token Management - Automatic CSRF token retrieval and caching
    • ✅ Hardware-Backed Authentication - Full HBA signature support
    • ✅ Challenge Handling - Captchas, 2FA, and other authentication challenges
    • ✅ Cookie Security - Secure cookie parsing and validation

    For advanced authentication challenges (captchas, 2FA), set up a global challenge handler:

    import { setHandleGenericChallenge } from 'rozod';

    setHandleGenericChallenge(async (challenge) => {
    // Handle captcha, 2FA, or other challenges
    // Return the challenge response or undefined to skip
    if (challenge.challengeType === 'captcha') {
    const solution = await solveCaptcha(challenge.challengeId);
    return {
    challengeType: challenge.challengeType,
    challengeId: challenge.challengeId,
    challengeBase64Metadata: solution
    };
    }
    });

    For Node.js environments requiring custom HBA keys:

    import { changeHBAKeys } from 'rozod';

    // Provide your own crypto key pair for HBA signatures
    const keyPair = await crypto.subtle.generateKey(
    { name: 'ECDSA', namedCurve: 'P-256' },
    true,
    ['sign', 'verify']
    );

    changeHBAKeys(keyPair);

    OpenCloud APIs require API keys in headers:

    import { fetchApi } from 'rozod';
    import { v2 } from 'rozod/lib/opencloud';

    const universeInfo = await fetchApi(
    v2.getCloudV2UniversesUniverseId,
    { universe_id: '123456789' },
    {
    headers: {
    'x-api-key': 'your_opencloud_api_key_here'
    }
    }
    );

    You can define custom endpoints for your specific needs:

    import { z } from 'zod';
    import { endpoint, fetchApi } from 'rozod';

    const myCustomEndpoint = endpoint({
    method: 'GET',
    path: '/v1/custom/:customId',
    baseUrl: 'https://my-api.example.com',
    parameters: {
    customId: z.string(),
    optional: z.string().optional(),
    },
    response: z.object({
    success: z.boolean(),
    data: z.array(z.string()),
    }),
    });

    const response = await fetchApi(myCustomEndpoint, { customId: '123' });

    This repository is maintained by Alrovi ApS, the company behind RoGold.

    RoZod is not affiliated with, maintained, authorized, endorsed, or sponsored by Roblox Corporation or any of its affiliates.