Webpage Screenshotter

unlisted

by cogscides

Capture webpage screenshots from note URLs and save them as vault attachments.

2 starsUpdated 1mo ago
View on GitHub

Webpage Screenshotter

Desktop-only Obsidian plugin that captures webpage screenshots with Playwright and saves them as vault attachments.

Core commands

Default command set:

  • Capture from URL
  • Run capture preset

Optional command set:

  • Run preset: <preset name> (registered only when Register custom preset commands is enabled)

Installation (development)

cd .obsidian/plugins/webpage-screenshotter
npm install
npx playwright install chromium
npm run build

Project structure

  • src/main.ts: plugin source entrypoint
  • src/styles.css: plugin styles source
  • main.js: build output loaded by Obsidian (ignored by git)
  • styles.css: copied from src/styles.css during build
  • scripts/sync-version.mjs: syncs package.json version into manifest.json and versions.json
  • scripts/prepare-release.mjs: version bump + sync + build

Release flow

Local release prep

# patch|minor|major|1.2.3
npm run release:prepare -- patch

This will:

  • bump package.json version (without creating a git tag)
  • sync manifest.json and versions.json
  • build main.js and copy styles.css

GitHub Actions

  • CI: lint + build on PR/push to main
  • Prepare Release: manual version bump + commit + tag
  • Release: on v* tags, builds and uploads plugin assets

Settings

General

  • Output folder: vault-relative target folder for screenshots
  • URL property key: frontmatter key used by active-note URL captures
  • Register custom preset commands: toggles runtime registration of non-default preset commands

Capture defaults

  • Default full page
  • Viewport width / Viewport height
  • Wait ms / Timeout ms / Wait until
  • Image type / Image quality
  • Selector (optional element capture)
  • Filename template
  • Embed width enabled / Embed width

Default filename template:

  • screenshot_{{DATE:YYMMDDHHmm}}-{{VIEWPORT_WIDTH}}x{{VIEWPORT_HEIGHT}}

If extension is omitted, the plugin appends the selected image type extension.

Frontmatter mapping

Rules are evaluated only when enabled.

Default rules:

  • screenshot = {{IMAGE_WIKILINK}} (enabled)
  • screenshotCaptured = {{DATE}} (disabled)

Command presets

Preset list behavior:

  • sorted alphabetically by preset name
  • edits are draft-based
  • Save presets saves and refreshes command registration
  • Cancel changes appears only when drafts differ from persisted settings
  • Restore missing default presets is always available and opens a selector
  • restore selector supports per-preset restore and Restore All when multiple defaults are missing

Template tokens

Date-aware token:

  • {{DATE}} default format: YY-MM-DD
  • {{DATE:<moment-format>}} e.g. {{DATE:YYMMDDHHmm}}

Direct substitution tokens:

  • {{URL}}
  • {{NOTE_TITLE}}, {{NOTE_PATH}}
  • {{IMAGE_FILENAME}}, {{IMAGE_BASENAME}}, {{IMAGE_EXTENSION}}, {{IMAGE_PATH}}
  • {{IMAGE_WIKILINK}}, {{IMAGE_EMBED}}, {{EMBED_WIDTH}}
  • {{FULL_PAGE}}, {{VIEWPORT_WIDTH}}, {{VIEWPORT_HEIGHT}}
  • {{IMAGE_TYPE}}, {{IMAGE_QUALITY}}
  • {{WAIT_UNTIL}}, {{WAIT_MS}}, {{TIMEOUT_MS}}, {{SELECTOR}}

Token UX in settings:

  • grouped legend with descriptions/examples
  • click token to copy
  • {{ input autocomplete in template fields

Runtime behavior

  • api.capture() requires a URL (or a preset flow that collects URL)
  • api.captureFromActiveNote() reads URL from the active note frontmatter using configured key
  • active-note capture throws when no markdown file is active or URL property is missing/empty
  • when pasteMode is enabled, paste targets the active markdown editor only
  • clipboard copy uses Electron APIs and is desktop-only
  • output filename is sanitized and extension-normalized (png|jpeg|jpg|webp)

API

const api = app.plugins.plugins['webpage-screenshotter'].api

const result = await api.capture(options?)
const result2 = await api.captureFromActiveNote(options?)
await api.runPreset(presetId, overrides?)
await api.applyFrontmatter(result, filePath?, rules?)
const text = api.renderTemplate(template, result, filePath?)
const presets = api.listPresets()
const settings = api.getSettings()

Capture result reference

capture(), captureFromActiveNote(), and runPreset() all resolve to:

  • ok: true
    • Always true for successful captures.
  • url: string
    • Final URL used for capture.
  • outputPath: string
    • Vault-relative path where image was written.
  • outputFileName: string
    • Basename including extension (for example shot.png).
  • outputBaseName: string
    • Basename without extension.
  • outputExtension: string
    • Extension without dot.
  • absoluteOutputPath: string
    • Absolute filesystem path (used for clipboard load).
  • wikilink: string
    • Obsidian wikilink to file (for example [[shot.png]]).
  • embed: string
    • Obsidian embed (![[shot.png]] or width form like ![[shot.png|720]]).
  • capturedAtIso: string
    • ISO timestamp for capture completion.
  • activeFilePath: string | null
    • Active markdown file path when available, otherwise null.
  • captureParams: object
    • Effective capture parameters after applying defaults + overrides.
    • fields: fullPage, viewportWidth, viewportHeight, waitForMs, timeoutMs, waitUntil, imageType, imageQuality, selector, embedWidthEnabled, embedWidth.

Notes for developers:

  • captureParams reflects normalized values used for Playwright and template token rendering.
  • embed and wikilink are prebuilt helpers; you usually do not need to construct these manually.

Templater examples

For plugin developers

Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.