sjht-web-screenshot

Capture screenshots of web pages running on local or remote servers using Puppeteer in headless Chromium. Use when user asks to screenshot web pages, capture...

MIT-0 · Free to use, modify, and redistribute. No attribution required.
0 · 79 · 0 current installs · 0 all-time installs
MIT-0
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
high confidence
Purpose & Capability
The name/description, SKILL.md, and the included Node script all align: the tool captures screenshots, supports SPA form login and direct Pinia store login, and writes PNGs/result.json. One inconsistency: the registry metadata lists no required binaries/env but SKILL.md and the script clearly require Node, puppeteer-core, and a Chromium binary (e.g. /usr/bin/chromium-browser). This is likely an omission in metadata rather than malicious.
Instruction Scope
SKILL.md instructs running the included script with a JSON config file; the script reads only that provided config, navigates to baseUrl/pages, and writes screenshots/result.json to the configured outputDir. It executes arbitrary JS inside the target pages (page.evaluate) to set input values, call Pinia store methods, and invoke Vue router — this is necessary for the claimed SPA login/navigation features but means the skill will run code inside whatever page you point it to (so pointing at untrusted sites or injecting untrusted config could expose page-local secrets).
Install Mechanism
This is an instruction-only skill with a shipped script; there is no install hook or remote download. That keeps risk low. The SKILL.md asks you to ensure puppeteer-core and Chromium are present (no installer provided), so the operator must install those dependencies manually.
Credentials
The skill requests no environment variables or credentials from the runtime environment. The only credentials it uses are those you provide in the config JSON (username/password or storeLogin args). There are no other undeclared secrets or credentials in the files.
Persistence & Privilege
always is false and the skill doesn't attempt to modify agent/system-wide configuration. It creates files in the supplied outputDir (as expected). It does run Chromium with --no-sandbox flags (common for CI/headless usage) — not a privilege escalation request from the skill, but an operational note.
Assessment
This skill appears to do what it says: run a Node script that drives headless Chromium to capture screenshots and optionally perform SPA login. Before using it: 1) Verify and install dependencies (Node, puppeteer-core, and a Chromium binary at the expected path) since the registry metadata omitted them. 2) Do not point baseUrl to untrusted third-party sites — the script runs arbitrary JS in-page (including calling app internals) which could access page-local secrets/cookies. 3) Protect credentials: the login credentials live in the config JSON you pass; treat that file securely and avoid storing plaintext secrets in shared locations (use ephemeral files or limited-permission directories). 4) Avoid writing outputDir as root-owned system paths unless intended. 5) Consider running the tool in a sandboxed container or VM because Chromium is launched with --no-sandbox (common for headless automation but reduces process isolation). If you want stronger assurance, request the publisher to declare required binaries in registry metadata and provide a vetted installation path for puppeteer-core.

Like a lobster shell, security has layers — review code before you run it.

Current versionv1.0.0
Download zip
latestvk973spk3x03qc7v2r5qf1bjkkx83d36q

License

MIT-0
Free to use, modify, and redistribute. No attribution required.

SKILL.md

Web Screenshot

Capture screenshots of web pages (especially SPA applications) with automatic login handling.

Dependencies

  • puppeteer-core (npm global)
  • chromium-browser (/usr/bin/chromium-browser)
  • Node.js

Verify with: which chromium-browser && npm ls -g puppeteer-core

Quick Start

node <skill_dir>/scripts/screenshot.js <config.json>

Config Format

{
  "baseUrl": "http://192.168.7.66:8080",
  "outputDir": "/root/screenpics/my-capture",
  "resolution": [1920, 1080],
  "login": {
    "url": "/login",
    "usernameSelector": "input[placeholder='请输入用户名']",
    "passwordSelector": "input[type='password']",
    "submitSelector": "button.el-button--primary",
    "credentials": { "username": "admin", "password": "123456" }
  },
  "pages": [
    { "name": "01_dashboard", "path": "/dashboard", "waitMs": 3000 },
    { "name": "02_project_list", "path": "/project/list", "waitMs": 2000 }
  ],
  "descriptions": {
    "01_dashboard": "工作台首页,展示KPI卡片和图表。",
    "02_project_list": "项目管理列表页面。"
  }
}

Login Flow (SPA Authentication)

The script handles Vue/React SPA login by:

  1. Navigating to the login page
  2. Setting input values via native HTMLInputElement.value setter + dispatching input events (Vue-reactive compatible)
  3. Clicking the submit button
  4. Waiting for SPA router navigation (URL change)
  5. Using Vue's $router.push() for subsequent page navigation (avoids Pinia/Redux store reset on full page reload)

Fields

FieldRequiredDescription
baseUrlBase URL of the web app
outputDirOutput directory for screenshots
resolutionNoViewport size [width, height], default [1920, 1080]
loginNoLogin config (skip for public pages)
login.usernameSelector✅*CSS selector for username input
login.passwordSelector✅*CSS selector for password input
login.submitSelector✅*CSS selector for submit button
login.credentials✅*{ username, password }
pagesArray of pages to capture
pages[].nameFilename prefix (e.g. 01_dashboard)
pages[].pathURL path (e.g. /dashboard)
pages[].waitMsNoExtra wait in ms after navigation (default 2000)
descriptionsNoMap of name → description text (included in result.json)

Output

  • {outputDir}/{name}.png — one PNG per page
  • {outputDir}/result.json — metadata with filenames, titles, URLs, descriptions

result.json Format

{
  "project": "auto-generated",
  "captureDate": "2026-03-22",
  "baseUrl": "...",
  "resolution": "1920x1080",
  "screenshots": [
    {
      "filename": "01_dashboard.png",
      "title": "Dashboard",
      "url": "...",
      "description": "..."
    }
  ]
}

Capture Login Page Too

To include the login page as the first screenshot, add it to pages with a special flag:

{
  "pages": [
    { "name": "00_login", "path": "/login", "isLoginPage": true, "waitMs": 2000 }
  ]
}

When isLoginPage: true, the script captures this page before performing login.

Advanced: Custom Vue Store Login

If the form-based login doesn't work (e.g., custom auth flow), use storeLogin instead:

{
  "login": {
    "url": "/login",
    "storeLogin": {
      "storeName": "user",
      "method": "login",
      "args": ["平台管理员"]
    }
  }
}

This directly calls pinia._s.get(storeName).method(...args) via CDP.

Troubleshooting

  • Blank charts (ECharts/Chart.js): Headless Chromium has no GPU. Charts using Canvas may render empty. Use --disable-gpu (already included).
  • Redirected to login on all pages: Login failed. Check selectors match the actual form elements. Try storeLogin approach.
  • SPA navigation not working: Ensure login section is configured. Without login, page.goto() is used instead of $router.push().

Files

2 total
Select a file
Select a file to preview.

Comments

Loading comments…