pages
List the pages of a stored audit with their titles, descriptions, links and flags
An issue list only shows the pages that break a rule. The pages command lists every page the audit crawled, one row each, so you can read a site’s titles and descriptions side by side, spot orphans, or see that every post title ends in the same suffix.
Every column is data the audit already stored: the pages, their extracted features, their links and the rule results. The command fetches nothing, so it is instant and costs no credits.
Usage
squirrel pages [options]Options
| Option | Alias | Description | Default |
|---|---|---|---|
--crawl | Crawl ID (or 8-character prefix) to read; repeat twice with --diff | latest audit | |
--diff | Compare two audits of the site: pages added, removed and changed | false | |
--format | -f | Output format: json, csv, markdown, html (markdown, json or csv with --diff) | console table, or markdown when piped |
--output | -o | Write to a file instead of stdout | - |
--missing | Only pages missing title, description, h1 or schema (repeatable or comma-separated) | all | |
--duplicate | Only pages the audit flags as a duplicate title or description (repeatable or comma-separated) | all | |
--too-long | Only pages with a title over 75 or a description over 160 characters | false | |
--orphan | Only pages the audit flags as orphans: fewer internal links to them than the orphan rule’s minimum (2 by default). A crawl the rule skipped (a capped crawl) flags nothing | false | |
--section | Only pages under this URL path, for example /blog; case-insensitive, and /café matches /caf%C3%A9 | all | |
--page | Only pages whose URL contains this text, case-insensitive (repeatable; a comma splits the value) | all |
Filters combine: a page has to match every filter you pass. Within --missing, --duplicate and --page, matching any one value is enough.
# Blog posts with no description
squirrel pages --section /blog --missing description
# Every page as a spreadsheet
squirrel pages -f csv -o pages.csvColumns
| Column | Meaning |
|---|---|
url | The URL the crawl requested |
finalUrl | Where it was served from after redirects (the same as url when it did not redirect) |
status | HTTP status |
depth | Clicks from the start URL |
canonical | The page’s canonical URL, if it declares one |
noindex | The page asks not to be indexed (meta robots or X-Robots-Tag) |
title, titleLength | The <title> and its length in characters |
description, descriptionLength | The meta description and its length |
h1Count | Number of <h1> elements |
h1 | Text of the first <h1> |
headingCount | Number of headings, h1 to h6 |
wordCount | Words of visible content |
schemaTypes | schema.org @type values declared on the page |
schemaIds | JSON-LD @id values declared on the page (the first 20) |
inlinks | Crawled pages that link here, each counted once |
internalOutlinks | Links from this page to other pages of the same site |
externalOutlinks, externalDomains | Links to other sites, and the hosts they point at |
loadTimeMs | Response time of the fetch |
lastModified | The Last-Modified header, if the server sent one |
flags | What the audit found on the page (below) |
A link to the page itself is neither an in-link nor an out-link. Pages that differ only by their query string (/items?id=1 and /items?id=2) keep their own out-links, but share one inlinks count, because the orphan and internal-link rules count links to a page without its query string. Links come from the pages’ stored parse, the same source the orphan and internal-link rules read, so a nofollow link counts here even though the orphan rule does not count it.
Flags
The flags column comes from the audit’s own rule results, so the table and the issue list agree.
| Flag | Set when |
|---|---|
title | core/meta-title warned or failed on the page |
description | core/meta-description warned or failed |
h1 | core/h1 warned or failed |
title-not-unique | core/title-unique names the page |
duplicate-title | content/duplicate-title names the page |
duplicate-description | content/duplicate-description names the page |
orphan | links/orphan-pages names the page |
canonical | core/canonical warned or failed |
robots | core/robots-meta warned or failed |
thin-content | content/word-count warned or failed |
noindex | The page asks not to be indexed (a fact from the crawl, not a rule) |
no-schema | The page answered with a success status and declares no schema.org type (also a fact) |
--duplicate and --orphan select on these flags, so they list exactly the pages the issue list names. A rule that was disabled, or skipped for the audit, sets no flag. --missing and --too-long read the columns themselves, and --missing only judges pages that answered below 400 and were parsed (a PDF, an image or a 404 has no title to be missing): the title and description limits are the rules’ defaults (75 and 160 characters), so a site that changed max_length in squirrel.toml sees its own limit in the title and description flags instead.
h1, headingCount and schemaIds are read from the page’s stored parse, the same parse the links come from; a page that was not parsed (a PDF, an image, an error page) has none of them. Anchor text is not a column: use squirrel entities for the declared schema graph.
Output formats
With no --format you get a console table of the first 50 pages on a terminal, and markdown when the output is piped or goes to a file, so squirrel pages | ... is parseable without a flag.
| Format | What you get |
|---|---|
json | { site, crawlId, startedAt, total, filtered, pages: [...] }: total is every page in the audit, filtered is how many matched, pages holds the rows with every column |
csv | One header row and a row per page. List columns (schemaTypes, externalDomains, flags) join with a space. A cell that starts with =, +, - or @ is prefixed with an apostrophe so a spreadsheet does not run it as a formula |
html | One standalone page, no network requests, with the table sortable by any column and filterable by text and by flag. At most 5,000 rows are inlined (the page says when more matched; use csv or json for all of them) |
markdown | A table of the columns a person scans: URL, status, title and length, description and length, H1 count, words, schema, in and out links, flags |
Titles, descriptions and URLs come from the audited site, so each format treats them as hostile. The console, csv, markdown and html outputs remove control characters, escape sequences, invisible characters and bidirectional overrides, a pipe in a URL is escaped so it cannot end a markdown table cell, and csv prefixes a formula start with an apostrophe. json keeps the text and writes DEL, the C1 controls, bidirectional overrides, invisible characters and line separators as \uXXXX, so the file is safe to print and the value is unchanged.
Comparing two audits
--diff shows what changed between two audits of the same site, which is how you check a fix: did the title rewrite land, did the 404 go away, did a page lose its schema.
# The latest audit against the one before it
squirrel pages --diff
# A named audit against the one before it, or two named audits
squirrel pages --diff --crawl 4f2ab91c
squirrel pages --diff --crawl 4f2ab91c --crawl 9a01c3dePages are matched by URL. The report lists the pages added (only on the newer audit), removed (only on the older one) and changed, with each changed field’s before and after: status, finalUrl, canonical, noindex, title, description, h1Count, h1, schemaTypes, schemaIds and flags. Counts that move with every crawl (links, word count, load time) are not compared. A list compares as a set, so a reorder is not a change.
With one audit named, or none, the older side is the audit of the same site that ran just before it. The store holds every project, so without that rule “the two newest audits” would often be two different sites. Naming two audits compares exactly those, in whichever order you give them, even across sites. With only one audit of the site, the command says so and exits 0; if the earlier audit was reclaimed (squirrel self disk --prune) it says that instead. When the two audits crawled clearly different numbers of pages (a quick audit against a full one, a difference of more than 20%), the markdown adds a note and the JSON a scopeNote, because pages then come and go with the crawl’s scope and not with the site. More than two --crawl values is a usage error.
--diff takes markdown (default), json or csv. --section and --page narrow both sides. --missing, --duplicate, --too-long and --orphan are rejected with --diff: they select on the state a diff compares, so a page whose title was fixed would stop matching --missing title on the newer side and be reported as removed.
Exit codes
The command exits 0 whenever it has an answer: an audit with no matching pages prints an empty table, and a store with no audit prints how to create one. It exits 1 for a usage mistake (an unknown --missing, --duplicate or --format value) or a project store it cannot read. --diff with a format it does not support, or with a state filter, is also a usage error.
Related
squirrel reportfor the findings, and--include-pagesfor a per-page list inside the JSON reportsquirrel entitiesfor the schema.org graph