Getting OG Image from deployment preview

Hello, I’ve had an idea of getting image from deployment preview and use that as a og:image, what I’ve done is that I wrote this endpoint in /pages/api/og.ts.

When I’ll take look at the code, it is clear and it suppose to work, but the endpoint for getting the image is “secured” from fetching without some auth method of yours, my question is, is this funcitonality disabled on purpose, or there’s any other solution on that?

import type { NextApiRequest, NextApiResponse } from "next";

const token = process.env.VERCEL_TOKEN;
const projectName = process.env.VERCEL_PROJECT_NAME;

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse,
) {
  try {
    if (!token || !projectName) {
      return res.status(500).json({
        error: "Missing VERCEL_TOKEN or VERCEL_PROJECT_NAME",
      });
    }

    const deploymentsRes = await fetch(
      `https://api.vercel.com/v6/deployments?project=${projectName}&limit=1`,
      {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      },
    );

    const deploymentsData = await deploymentsRes.json();
    const deploymentId = deploymentsData?.deployments?.[0]?.uid;

    if (!deploymentId) {
      return res.status(500).json({
        error: "Deployment ID not found",
        debug: deploymentsData,
      });
    }

    const deploymentDetailRes = await fetch(
      `https://api.vercel.com/v13/deployments/${deploymentId}`,
      {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      },
    );

    const deploymentDetail = await deploymentDetailRes.json();
    const teamId = deploymentDetail?.team?.id;

    if (!teamId) {
      return res.status(500).json({
        error: "Team ID not found in deployment detail",
        debug: deploymentDetail,
      });
    }

    const screenshotUrl = `https://vercel.com/_next/image?url=%2Fapi%2Fscreenshot%3Fdark%3D0%26deploymentId%3D${deploymentId}%26teamId%3D${teamId}%26withStatus%3D1&w=1920&q=75`;

    console.log("✅ Screenshot URL:", screenshotUrl);

    const imageResponse = await fetch(screenshotUrl);

    if (!imageResponse.ok) {
      const errorText = await imageResponse.text();

      return res.status(500).json({
        error: "Failed to fetch screenshot image",
        response: errorText,
      });
    }

    const buffer = await imageResponse.arrayBuffer();

    res.setHeader("Content-Type", "image/png");
    res.setHeader("Cache-Control", "public, max-age=86400");

    return res.status(200).send(Buffer.from(buffer));
  } catch (err) {
    console.error("[OG] Unexpected error:", err);

    return res
      .status(500)
      .json({ error: "Unexpected error", detail: String(err) });
  }
}

Unfortunately this is not supported, the internal deployment previews are secured along with the rest of your account information and can’t be queried from the outside

If you want to use a screenshot of your page as the OG image you’ll need to generate it yourself, either

  • using vercel/og to recreate it as an image
  • using a screenshot service
  • or building your own with puppeteer
2 Likes

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.