如何对已认证页面(登录门控内容)进行截图

发布: (2026年2月26日 GMT+8 16:16)
5 分钟阅读
原文: Dev.to

Source: Dev.to

概览

捕获公共 URL 很简单。捕获仪表板、发票或任何需要登录的页面时,传统的无头浏览器自动化会出现问题:你需要先登录,保留会话 cookie,将其传递给截图请求,并处理会话过期。

PageBolt 允许你直接传递 cookie 和 header —— 无需登录自动化。

如果你的应用使用基于 Cookie 的会话(大多数服务器渲染的应用都是如此):

const res = await fetch("https://pagebolt.dev/api/v1/screenshot", {
  method: "POST",
  headers: {
    "x-api-key": process.env.PAGEBOLT_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://yourapp.com/dashboard",
    cookies: [
      {
        name: "session",
        value: "your-session-token-here",
        domain: "yourapp.com",
      },
    ],
    fullPage: true,
    blockBanners: true,
  }),
});

const image = Buffer.from(await res.arrayBuffer());

通过请求头传递 Bearer 令牌

对于使用 Authorization 请求头的单页应用和 API:

const res = await fetch("https://pagebolt.dev/api/v1/screenshot", {
  method: "POST",
  headers: {
    "x-api-key": process.env.PAGEBOLT_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://yourapp.com/reports/q4-2024",
    headers: {
      Authorization: `Bearer ${userToken}`,
    },
    fullPage: true,
  }),
});

多个 Cookie(例如 CSRF + 会话)

某些框架需要同时使用会话 Cookie 和 CSRF 令牌:

body: JSON.stringify({
  url: "https://yourapp.com/admin/users",
  cookies: [
    { name: "session_id", value: sessionId, domain: "yourapp.com" },
    { name: "csrf_token", value: csrfToken, domain: "yourapp.com" },
  ],
}),

在应用内部(服务器端)生成截图

内部工具最简洁的模式:在服务器上生成一个短期有效的令牌,将其嵌入 URL,截取页面截图,然后使令牌失效。

// Express route — generates signed URL, screenshots it, returns PDF
app.get("/invoices/:id/pdf", requireAuth, async (req, res) => {
  const { id } = req.params;

  // Create a single‑use signed token
  const token = await db.signedTokens.create({
    invoiceId: id,
    userId: req.user.id,
    expiresAt: new Date(Date.now() + 60_000), // 1 minute
  });

  const signedUrl = `https://yourapp.com/invoices/${id}?token=${token.value}`;

  const pdfRes = await fetch("https://pagebolt.dev/api/v1/pdf", {
    method: "POST",
    headers: {
      "x-api-key": process.env.PAGEBOLT_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ url: signedUrl }),
  });

  const pdf = Buffer.from(await pdfRes.arrayBuffer());

  // Expire the token immediately
  await db.signedTokens.expire(token.id);

  res.setHeader("Content-Type", "application/pdf");
  res.setHeader(
    "Content-Disposition",
    `attachment; filename="invoice-${id}.pdf"`
  );
  res.send(pdf);
});

这样可以避免将长期有效的凭证传递给第三方服务——令牌仅在 60 秒内有效,使用后即被作废。

为用户代表捕获仪表板

对于需要向用户发送其账户状态截图的 SaaS 应用:

async function captureUserDashboard(userId) {
  // Get the user's current session token from your DB
  const user = await db.users.findById(userId);
  const sessionToken = await generateSessionToken(user);

  const res = await fetch("https://pagebolt.dev/api/v1/screenshot", {
    method: "POST",
    headers: {
      "x-api-key": process.env.PAGEBOLT_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      url: `https://yourapp.com/users/${userId}/dashboard`,
      cookies: [
        {
          name: "session",
          value: sessionToken,
          domain: "yourapp.com",
        },
      ],
      fullPage: true,
      blockBanners: true,
      blockAds: true,
    }),
  });

  return Buffer.from(await res.arrayBuffer());
}

// Send weekly dashboard screenshot to all users
async function sendWeeklyDigest() {
  const users = await db.users.findActive();
  for (const user of users) {
    const image = await captureUserDashboard(user.id);
    await email.send({
      to: user.email,
      subject: "Your weekly summary",
      attachments: [{ filename: "dashboard.png", content: image }],
    });
  }
}

Python 示例

import os
import requests

def screenshot_authenticated(url: str, session_cookie: str) -> bytes:
    resp = requests.post(
        "https://pagebolt.dev/api/v1/screenshot",
        headers={"x-api-key": os.environ["PAGEBOLT_API_KEY"]},
        json={
            "url": url,
            "cookies": [
                {
                    "name": "session",
                    "value": session_cookie,
                    "domain": url.split("/")[2],
                }
            ],
            "fullPage": True,
            "blockBanners": True,
        },
    )
    resp.raise_for_status()
    return resp.content

image = screenshot_authenticated(
    "https://yourapp.com/dashboard",
    session_cookie="your-session-token"
)
with open("dashboard.png", "wb") as f:
    f.write(image)

什么不起作用(以及原因)

传统的——通过一系列点击自动化登录——方法很脆弱,因为它依赖于 UI 稳定性、时机,一旦登录流程有任何变化就会失效。使用 PageBolt 的 cookie/header 注入方式要可靠得多,也更易维护。

传统认证面临的挑战

  • 登录表单布局会变化 → 自动化失效
  • CAPTCHA 和机器人检测会拦截无头浏览器
  • MFA 流程难以自动化
  • 自动化登录得到的会话 cookie 的过期方式与 API 令牌不同

解决方案

直接传递 cookie 或 header 可以规避上述所有问题。先在服务器端生成令牌(你可以自行控制认证逻辑),将其传递给捕获请求,并在使用后立即失效。

免费试用 — 每月 100 次请求,无需信用卡。 → 2 分钟快速入门

0 浏览
Back to Blog

相关文章

阅读更多 »

第27天 #100DaysOfCode — REST API

不管你是否意识到,每当一个应用发送请求并接收响应时,你已经在使用 REST APIs 了。你的天气应用、你的社交动态……