DIYgod/RSSHub · error · Error

Failed to parse page data

Error message

Failed to parse page data

What it means

extractInitials() either failed to match the /window\.initials\s*=\s*(\S[\s\S]*?);?$/ regex (throws 'initials not found') or JSON.parse failed on the captured payload. The handler swallows that detail and re-throws a generic 'Failed to parse page data'.

Source

Thrown at lib/routes/xhamster/index.ts:117

}

async function handler(ctx) {
    const { creators } = ctx.req.param();
    const pageUrl = `https://xhamster.com/creators/${encodeURIComponent(creators)}/newest`;

    const response = await got(pageUrl);

    const $ = load(response.data);
    const initialsRaw = $('#initials-script').text();
    if (!initialsRaw) {
        throw new Error('Could not locate initials script on page');
    }

    let initials: Initials;
    try {
        initials = extractInitials(initialsRaw);
    } catch {
        throw new Error('Failed to parse page data');
    }

    const creatorName = initials.infoComponent?.pornstarTop?.name ?? creators;
    const videos = initials.trendingVideoSectionComponent?.videoListProps?.videoThumbProps ?? [];

    const items = videos.map((video) => ({
        title: `${video.title}${video.isUHD ? ' [4K]' : ''}`,
        link: video.pageURL,
        pubDate: video.created ? parseDate(video.created * 1000) : undefined,
        author: creatorName,
        description: renderDescription(video),
        media: {
            content: {
                url: video.trailerURL ?? video.pageURL,
                type: 'video/mp4',
                ...(video.duration && { duration: video.duration as unknown as string }),
            },
            thumbnail: {

View on GitHub (pinned to bed535e087)

Solutions

  1. Inspect the raw #initials-script text from the RSSHub host to see the new format.
  2. Update the extractInitials regex/parse logic at index.ts:62-68 to match the current serialization.
  3. Report upstream (maintainer eve2ptp) with a sample of the new script payload.

Example fix

// before
const match = scriptContent.match(/window\.initials\s*=\s*(\S[\s\S]*?);?$/);
// after (tolerate trailing content / type-tagged JSON)
const match = scriptContent.match(/window\.initials\s*=\s*(\{[\s\S]*?\})\s*;?\s*(?:<\/script>)?$/);
Defensive patterns

Strategy: type-guard

Validate before calling

// Validate the script payload shape before parsing
const raw = $('#initials-script').text();
if (!/window\.initials\s*=/.test(raw)) {
    throw new Error('initials assignment missing — page format changed');
}
if (!raw.includes('{') || !raw.includes('}')) {
    throw new Error('initials payload does not look like JSON');
}

Type guard

function isXhamsterParseError(e: unknown): boolean {
    return e instanceof Error && /Failed to parse page data/i.test(e.message);
}

Try / catch

try {
    initials = extractInitials(initialsRaw);
} catch (parseErr) {
    // Preserve the real reason instead of masking it
    throw new Error(`Failed to parse xhamster initials: ${parseErr}`, { cause: parseErr });
}

Prevention

When it happens

Trigger: The #initials-script text exists but its format changed — trailing semicolon handling differs, the assignment was renamed, or the JSON is malformed/truncated — index.ts:114-118.

Common situations: xhamster changed how it serializes window.initials (e.g. now uses a JSON <script type="application/json"> instead), or the page injected extra content after the assignment that breaks the greedy regex.

Understand the failure class

Related errors


AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12). Data as JSON: /api/errors/7674a2ae20f1f96c. Report an issue: GitHub.