Tools
install, pair, list_browsers, list_tabs, scan_page, diff_captures, extract_design, storyboard_page and check_quotes, with every argument.
install
Sets up Page Scanner's helper for every Chromium browser on the computer, and returns which
browsers and what the user does next: press Connect in the extension's settings and allow
Chrome's prompt. Returns no secret. An unpacked build loaded in developer mode is found and
allowed by itself. One optional argument, extensionIds: more extension ids to allow by hand. See
Connecting Chrome.
pair
The older setup. Writes the pairing and returns the port and token to paste into Chrome. One
optional argument, rotate, which issues a new token and invalidates the old one. See the note in
Connecting Chrome about the token reaching the transcript.
list_browsers
No arguments. The Chrome profiles connected right now, with the name you gave each one and how long it has been connected. Start here when more than one is connected.
list_tabs
The windows and open tabs of one browser. Tabs carry the windowId they belong to, and windows
say which is focused, so an agent can pick a window as well as a tab.
| Argument | Meaning |
|---|---|
browserId | Which browser. Optional when only one is connected. |
waitSeconds | How long to wait for a browser to connect. 0 fails immediately. |
scan_page
Captures a page, or a list of them, and writes each to disk. Returns the absolute path.
| Argument | Meaning |
|---|---|
browserId | Which browser. Optional when only one is connected. |
tabId | A tab from list_tabs. Give one of tabId, url or urls. |
url | Opens a background tab there, captures it, closes it again. |
urls | Up to 50 addresses, captured one at a time into outputPath, which is then a directory. A page that fails is reported and the rest are captured. |
windowId | Which window to open url in. Ignored with tabId. |
format | pdf (default), png, jpeg. |
pageSize | PDF only. a4 (default) and letter slice onto printable sheets with a half-inch margin; phone cuts it into phone screens, 390 × 844 px, with no margin; auto is one page the size of the capture. |
quality | JPEG only, 0.1 to 1. |
videoHandling | frame keeps a video's paused frame, blank leaves its area empty. |
colorScheme | Which of a page's two themes to capture: auto (default, whatever the browser shows), light, dark. |
captureWidth | Lay the page out at a sheet's width first, so the PDF prints at 1:1: window (default), a4, letter; or phone, 390 px, the page as a phone shows it. |
openEditor | Also leave the capture open in a Page Scanner editor tab. |
outputPath | A file, or a directory to keep the suggested name. A leading ~ is home. Defaults to the cwd, or ~/Downloads when that is / or read-only, as under Claude Desktop. |
markdown | The page as Markdown, read from the page rather than the PDF: inline returns it in the result, beside writes a .md next to the file, only writes the .md and no file. Adds page: title, address, capture time, language, headings. Pictures are left out. |
textOptions | How markdown is written, to fit a context window: scope (page, or main for the main content only), maxChars (200 or more, cut at a block boundary), links (inline, references, or text for no addresses), pictures (omit, or alt for a placeholder), redact (true replaces what Sensitive Text's rules and the user's patterns find with placeholders such as ⟦EMAIL 1⟧; the Markdown and the tables with it, not a file beside it). Only with markdown. |
hide | Clutter to hide before the capture and put back after: any of ads, consent, chat, overlays; [] hides nothing. Left out, the extension's own settings decide, and they hide all four unless the user changed them. The result counts what was hidden as hidden. |
slices | Also write the page as PNG slices top to bottom for looking at it with a vision model: true for at most 1568 px a side (past which Claude shrinks a picture), or a side in pixels from 256 to 4096 for another model. Each repeats the last 48 px of the one before. The result lists slices[] with each path and the band (y, height, CSS px) it shows, in a folder beside the file. |
pictureFiles | Also write the page's pictures and canvases (at least 120 by 40 px), cut from the capture where they were drawn, as PNGs in a folder beside the file. The result lists pictures[] with each path, kind (image or canvas) and box. |
accessibility | Also check the page against WCAG 2.0, 2.1 and 2.2 (levels A and AA) with axe-core, and write <name>.accessibility.pdf beside the file: the page with each failing element boxed and numbered, and the rules listed after it; and <name>.accessibility.json, every rule and element with its box in CSS px. The result's accessibility has both paths, the counts by impact and each rule; null when the check could not run on the page. An automated check finds some of what fails WCAG, not all. |
tables | The page's tables as rows of cell text, to read a table as data: inline returns them in the result as tables.tables, beside writes <name>.tables.json next to the file. Each has rows (every row as wide as the widest, an icon by its name), header (the first row is the page's header) and box (CSS px); tables.sizes gives each one's rows and columns. A <table>, an ARIA table and a CSS grid drawn as a table all count. With markdown, textOptions.scope and redact apply to them too. |
highlight | Passages you quoted from this page, highlighted in the file where the page has them as written (as check_quotes finds them), each listed under a "Quoted passages" bookmark in a PDF. The result's highlighted says which were found. One page only, not with urls. |
fileName | The file name inside outputPath, as a template: {n} (place in urls), {host}, {name} (the suggested name), {date}, {time}, {ext} (added when left out). A / makes a subdirectory. |
waitSeconds | How long to wait for a browser to connect. 0 fails immediately. |
timeoutSeconds | How long the browser may take over one page, in seconds, 1 to 1800. Default 120. Raise it for a very tall page, such as a long chat. Not how long the call waits: see below. |
A tall page or a long list can take the browser minutes, longer than some clients wait for one
call (60 seconds is the MCP SDK's default, and Claude Desktop's). A client that asks for progress
gets a notification every 10 seconds and the result at the end. One that does not gets
status: "running" after 45 seconds, with startedSecondsAgo and, for urls, pagesDone and
pages, while the capture goes on in the browser. Call scan_page again with exactly the same
arguments to wait for it: the call joins the running capture and returns its result, which is kept
for 10 minutes if it finishes while nobody is waiting. A capture of the same tab with other
arguments is refused until the first ends, because only one debugger can drive a tab at a time.
extract_design works the same way.
What comes back
The absolute path, the capture's width and height in CSS pixels, the mode (vector or
raster), selectableText, and truncated.
selectableText is true only for a PDF that came out of the vector pipeline, which is the thing
an agent should check before promising the text is real. truncated is null when the capture
was whole, and otherwise carries what the page measured, what was captured, and a sentence
naming the gap.
When anything was hidden, by hide or by the extension's settings, the result has hidden: how
many ads, consent banners, chat widgets and overlays the scan took out of the page before
capturing it.
When the page declares how to cite it (citation tags, schema.org data, Dublin Core, OpenGraph,
a canonical link), the result has citation: kind (journal, conference, thesis, report,
book, news, blog or webpage), and those of title, authors, published, modified,
container (the journal or site), publisher, volume, issue, pages, doi, isbn, issn,
canonical and language it gave, as it wrote them and unchecked, with from, the vocabularies
they came from. The file carries the same. A page that declares nothing, and an extension older
than this, give no citation.
When the browser had machine-translated the page before the scan (Chrome's or Edge's translator),
the result has translated: { "by": "chrome" } or "edge". The text is then the translation,
not the page's own words; the Markdown's front matter says translated: and the PDF's Subject
says so too. Quote such a page as a translation.
With markdown, the result also has page: title, url, capturedAt (ISO 8601), language
(the page's own lang, or null) and headings (level and text, in order), plus
markdownPath where the .md was written, or markdown with the text itself for inline. For
only, path is the .md. An extension older than this feature sends no text, and the call
fails with a sentence saying to update it.
With textOptions, page.scope says whether the main content was found and written, page.cut
(when maxChars left blocks out) gives the whole text's length and how many blocks went, and each
heading in page.headings has offset and chars: where its section starts in the text and how
long it is. With an extension older than this, the call fails with a sentence saying to update it.
Given urls, the answer is results, one per page in the list's order: that page's result with
ok: true and its url, or ok: false with an error carrying a code and a message. The
pages are captured one after another, so a list takes as long as its pages together, and a page
that fails does not stop the rest. written and failed count them. The call is an error as a
whole only when nothing could be scanned at all: no pairing, no browser, no daemon. For more than
50 addresses, call it again with the rest, or use the command line's --urls.
diff_captures
Says what changed between two captures of a page that scan_page wrote: two Markdown files a
passage at a time, or two PNGs pixel by pixel, outlining the changed regions on the newer one. For
PDFs, scan with markdown: "beside" and pass the PDFs or their .md files.
| Argument | Meaning |
|---|---|
oldPath | The older capture: a .md from markdown beside or only, a PNG, or a PDF with its .md beside it. |
newPath | The newer capture of the same page, of the same kind. |
outputPath | For two PNGs, where to write the newer one with the changed regions outlined. Defaults to <name>.diff.png. |
section | For Markdown, compare only the section under this heading, or a path of headings ("Pricing > Pro"). |
Returns kind (text or visual) and changed. For text: added and removed line counts,
hunks, the same as a unified diff, each side's source and captured from its front matter,
and sameAddress; with section, section says where each side has it (line, heading), or null for a side without it, which counts as a change. For pictures: regions (x, y, width, height in pixels of the newer
capture), changedFraction, both sides' sizes, and path, the outlined picture, or null when
nothing changed. No browser is needed: both captures are already on disk.
The picture comparison is by position, so content that moved down the page shows as changed below the move; the text comparison sees through that. JPEGs are refused.
extract_design
Reads a page's design, or several pages', in its light and its dark scheme and writes
tokens.json, tokens.css, tailwind.preset.js, audit.md, contrast.md and extract.json
into a directory, and components.json, components.md and catalog.pdf with components,
as page-scanner design does.
| Argument | Meaning |
|---|---|
browserId | Which browser. Optional when only one is connected. |
tabId | A tab from list_tabs, read as it stands. Give one of tabId, url, urls or crawl. |
url | Opens a background tab there, reloads it under each color scheme, reads it and closes it again. |
urls | Up to 20 pages of one site, read one after another and written as one design; audit.md lists what only one page uses. |
crawl | A start address: its same-origin links are followed, one page per kind, honoring robots.txt and nofollow, never a log-out or delete address; a page that lands on another site or a page already read is left out. |
maxPages | With crawl, the most pages to read. Default 10, at most 50. |
depth | With crawl, how many links from the start. Default 2, at most 5. |
outputPath | The directory. Defaults to design-<host> in the working directory, or in ~/Downloads as for scan_page. |
minUses | How many elements must use a value before it becomes an inferred token. Default 2. |
components | true to find the components as well: repeated structures and controls, their variants and hover and focus states, written to components.json and components.md, and catalog.pdf with each variant cut from the page as vector artwork. Each page is scanned too, so it takes longer. |
waitSeconds | How long to wait for a browser to connect. 0 fails immediately. |
timeoutSeconds | How long the browser may take over one page, in seconds, 1 to 1800. Default 120. Raise it for a very tall page, such as a long chat. Not how long the call waits: see below. |
Returns the directory and each file's path, the tokens counted by group, how many the page
declared, unusedDeclared (declared colors nothing was drawn in, left out), the contrast pairs
(pairs, failing below AA, and overImage, text over a gradient or picture left to the eye),
nearlyEqual, onePage (values only one page uses) and darkDiffers. pages lists every page
with ok and, when it was not read, message; in a crawl, landed and left say where a page
went and why it was left out, and crawl says whether robots.txt was read and which links were
passed over, by reason. With components, components counts the components and their
variants. Inferred tokens are numbered by use, not
named, so naming them is left to the agent.
storyboard_page
Scrolls a page from its top at 1.25 screens a second and records how it behaves as a
storyboard, as page-scanner storyboard does: a
PDF with an overview and a page for each scene with six frames from its entry to its exit, a
.json beside it with every scene measured, and the frames as JPEGs in a .frames folder. It is
the extension's Scan scrolling, asked for by an agent rebuilding a
page's scroll animations.
| Argument | Meaning |
|---|---|
browserId | Which browser. Optional when only one is connected. |
tabId | A tab from list_tabs, scrolled where you can see it. Give one of tabId or url. |
url | Opens a background tab there, scans its scroll and closes it again. |
windowId | Which window to open url in. Ignored with tabId. |
viewport | { "width": 390, "height": 844 }, each 240 to 3840 CSS px. A tab opened for url is scanned at 1440 by 900 without it; a tabId at its window's size, and put back after one. |
outputPath | Where to write the PDF; a directory keeps the suggested name. The .json and the .frames folder go beside it. |
waitSeconds | How long to wait for a browser to connect. 0 fails immediately. |
timeoutSeconds | How long the browser may take, 1 to 1800. Default 240: the scan scrolls for up to two minutes, then the PDF is built. |
Returns path, specPath and framesPath, and storyboard, the JSON itself: the address, the
viewport, the page's height, the pace, the color scheme, the libraries seen, the page's feel in a
sentence, ended (done, stopped, input or detached) and cut, and every scene with its
scroll range, kind (pinned, motion or scroll), title, moves (what moved, a sentence
each), text, media, feel (on the scenes that moved most) and keyframes, each with its
cell (0 to 5), scroll y, file and absolute path. A plain scroll has no keyframes. It takes
up to two minutes, so it answers the way scan_page does for a long capture: a client that asks
for progress gets it, and one that does not gets status: "running" and calls again with the
same arguments.
check_quotes
Before quoting a page in an answer, checks that each quote or value occurs in the capture's
Markdown as written, with the line and the section it is under. No browser and no model: the
agent writes, Page Scanner checks. The Markdown's own markup is undone first (escapes, emphasis,
link syntax, list and quote prefixes, table pipes) and line wrapping is ignored; a quote never
runs across two blocks, and a word or number has to stand apart (4.99 is not in $14.99).
| Argument | Meaning |
|---|---|
path | The capture's .md, as scan_page wrote it with markdown beside or only. Give this or markdown. |
markdown | The capture's Markdown as text, as scan_page returned it with markdown inline. |
quotes | The quotes and values to look for, as they will appear in the answer. 1 to 200. |
loose | true to accept a quote that matches only once curly quotes, dashes, the ellipsis and case are folded. |
Returns checked, found, missing and allFound, and a result per quote: match (exact,
loose or none), count, and occurrences, each a line and a section ("Pricing › Pro", or
front matter). A quote not found has near: the longest start of it the capture has, where, and
how each goes on from there, so the quote can be put right. The same check is
page-scanner check on the command line.