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) });
}
}