Content pruning review
Which pages on your site deserve a second look? Upload a Search Console Pages export over a long range and paste your sitemap. You get the addresses that had no impressions, when the export is complete enough to say so, and the lowest-traffic pages that did earn something. Each is a page to review, never a page this tool tells you to remove.
Your file never leaves your browser. It is read by JavaScript in this tab; there is no upload, and nothing is fetched: your sitemap is pasted or chosen from your disk, and none of its addresses is opened. This page's security policy blocks fetch, XHR, WebSocket, EventSource and beacon calls and form posts.
A short list to review, with its limits attached
Addresses with no row
Every address in your inventory that the Pages export has no row for. It is only printed when Google did not cut the table (a Search Console export of fewer than 1,000 rows, or a BigQuery bulk export table) and when the export was not filtered. Otherwise you get the reason and the fix, not a list that looks like an answer.
The lowest pages with a row
The pages that earned least but did earn something, ranked by clicks and then impressions. If the table was cut at 1,000 rows, the list says it is the lowest of what was kept, not the lowest on your site.
Review, not remove
A page on either list may need improving, merging into a stronger page, a redirect or a noindex rule, or nothing. The tool names the three things to check first (the canonical, a noindex rule, how new the page is) and never tells you to take a page down.
What to upload
1. The Pages export. In Search Console, choose your property and open Performance (Search results). Set the date range as long as you can: Search Console shows up to 16 months, and a page with no impressions over a short range may just be one that earns in another season. Leave the search type on Web and add no filter, because a filtered export leaves out pages that have impressions in the rest of Search. Open the Pages tab, then Export → Download CSV, and upload the ZIP (it carries the Filters file this tool reads to check the search type and the range) or the Pages file alone.
2. Your inventory. Paste your sitemap's XML, or choose the file, or paste one address per line. Google says a single sitemap holds at most 50,000 URLs, so a larger site has a sitemap index, which lists other sitemaps and not pages: open each sitemap it lists and paste or choose them one at a time. Nothing is fetched, so this tool cannot open them for you. Use the addresses you want in search, which is what a sitemap should hold.
3. A BigQuery table instead of the Pages export. If you keep Search Console's bulk export in BigQuery, one row per address can stand in for the Pages export. Google says a bulk export holds all the performance data available for your property except anonymized queries, so the 1,000-row limit of the Search Console export does not apply to it. It holds only the days since the export was set up: Google says to use the Search Console API or the reports for days before that. Google also says rows repeat keys, so the table has to be summed per address, as this query does:
SELECT url, SUM(clicks) AS clicks, SUM(impressions) AS impressions, SUM(sum_position) AS sum_position FROM searchconsole.searchdata_url_impression WHERE search_type = 'WEB' GROUP BY url
Keep the sum_position column: it is how this page knows the table is a bulk export. It is not a position, and this tool does not use it.
Do not add a LIMIT: it would cut the table the way the 1,000-row limit cuts a Search Console export, and a table of exactly 1,000 rows is
treated as cut. Download the result as CSV and upload it in box 1. The date range is not in the file, so check the table's earliest
data_date yourself.
How big a file it takes. This page opens up to 64 MB of files at once and reads up to 200,000 rows or 12 MB of table text, and says which limit it hit. A Search Console Pages table is at most 1,000 rows, so its export is a few hundred kilobytes; a BigQuery result can be much larger.
What the export cannot tell you
- 1,000 rows. Google says an export is truncated to 1,000 rows and that a table shows at most 1,000, while the totals in its reports are actual totals. The rows that are cut are the ones that earn least, which is exactly where the pages you are looking for are. So the “no row” list is only given when the table has fewer than 1,000 rows, and a 1,000-row table is described as cut. A BigQuery bulk export table is the exception: Google does not cut it, so the list is given for one of any size, with the limits that Methods lists for it.
- Canonical URLs. Google says most performance data is assigned to the page’s canonical URL, not to a duplicate, and that the Pages dimension is the final URL after redirects. An address in your inventory can therefore have no row because its traffic was credited to another address. The URL Inspection tool tells you the canonical Google chose for a page.
- noindex. Google drops a page with a noindex rule from its search results. A noindex page is meant to have no impressions, so it is not a finding that it has none.
- New pages. A page published inside the range has had fewer days than the range implies. The tool shows the sitemap’s
lastmodbeside an address when the sitemap has one, and marks a date inside the export’s range when the range is known. Alastmodis the last time the page was edited, not the day it was published. - Search, not value. A page with no Google Search impressions can still serve visitors who arrive from email, ads, other sites or your own navigation. This tool reads one channel.
- Filters and search type. A Pages export filtered to one country, device, query or page, or taken for another search type, would show “no row” for pages that have impressions elsewhere. The Filters file inside the ZIP is read for this, and a bare Pages file cannot be checked.
- Zeros. Values Search Console shows as
~or-are zeros in the download. A table copied from the screen still has them, which is not a number: this tool skips those rows and lists them under “What the parser could not read”. - Dates. The range is in Pacific Time and comes from the dates table or the Filters file when it states one. Search Console shows up to 16 months of data (Google’s post of 8 Jan 2018 introducing the new Search Console says “you’ll have 16 months of data”); the CSV you keep is yours.
What happens to your file
Nothing leaves your browser. The file and the sitemap are read by JavaScript running in this tab and parsed in memory; they are not uploaded, there is no copy on a server, and nothing from them is written to a cookie or to local storage (the theme switch remembers light or dark and nothing else). The page loads no analytics and no third-party scripts, and it opens none of the addresses in your inventory.
You do not have to take our word for it. Open your browser's developer tools, choose the Network tab, run a review, and
watch it make no request. Two things back that up. This page carries a content security policy, readable in its source,
that blocks fetch, XHR, WebSocket, EventSource and beacon calls (connect-src 'none') and form posts
(form-action 'none'), and allows images only as inline data: URIs. A content security policy
does not cover every browser feature (WebRTC, for one), so the second check matters: the project's tests read this page's
own script and every module it imports, and fail on any of the browser's network APIs.
The site-wide script penlid.js, which every page loads, contains network calls for the signed-in app's
account switcher. This page never calls it, and a test checks that those calls sit only inside the switcher.
The one thing that leaves this page's memory is the one you ask for: the CSV you click to download.
Methods: the rules and thresholds
Each number below is a constant in public/assets/lib/page-tools.js (the read-size limit is in tool-ui.js and gscsv.js). The project's tests compare the numbers quoted here with those constants; that is a check on the numbers, and not on every sentence. They are judgement calls, and they are the owner's to change.
- Reading the files
- A table is recognised by its columns, not its name. The Pages table is the one with a page column and a clicks or impressions column; a table taken with Compare, which holds two periods, is refused. Two exports are never added together. A row with a negative or fractional value is not used and is named. A row whose cell is
~or-is skipped and named, not read as 0. Everything the parser skipped, ignored or read as zero (rows, columns, a second table, blank cells) is listed under “What the parser could not read” at the top of the result. A table in which every row is unusable is refused. - Matching addresses
- Addresses are compared after dropping the scheme, a leading
www., trailing slashes and a #fragment, keeping the query string, with the host in lower case and the path as written; percent-escapes are decoded, so%C3%A9and an accented letter are one address. Two spellings of one address in the export are added together and said so. When one side has no host, a path is matched only if exactly one export row has that path. Nothing is matched by resemblance. - The inventory
- A sitemap is read for the
<loc>and<lastmod>of each<url>; a sitemap index is refused with the sitemaps it lists. Anything else is read as one address per line, taking the first word of each line and skipping blank lines and lines that start with #. An entry that is not an address (it must start with http:// or https://, or with one slash, or be a host with a dot; ftp:, file: and javascript: entries are not addresses) is skipped and named. At most 50,000 addresses are read, which is Google’s limit for one sitemap. - The “no row” list
- An inventory address with no row, or a row reading 0 impressions. It is withheld, with the reason, when the Pages table has 1,000 or more rows (Google’s limit); when the Filters file shows a search type other than Web or any other filter; when no inventory address matched any row; or when there is no inventory. It is also withheld when the parser skipped or could not use any row of the Pages table, because that row may be an address in your inventory (a summary row such as “Grand total” is not a page and does not count). A table with 999 rows is not cut by that limit. A table with the columns of a BigQuery bulk export is not held to that rule: see “BigQuery bulk export tables” below.
- BigQuery bulk export tables
- A table with the columns
url,impressionsandsum_positionis read as the URL table of Google’s bulk export,searchdata_url_impression, whatever other columns it has. Google says a bulk export holds all the performance data available for the property except anonymized queries, so such a table is not held to the 1,000-row rule: the “no row” list is given for one of any size, unless another gate withholds it. Four limits remain. A table of exactly 1,000 rows is treated as cut, because a query can cut a table and Google’s own sample queries end inLIMIT 1000. An export holds only the days since it was set up, and the file does not say which days it covers, so the page says its range is not stated. A page whose impressions all came from anonymized queries is not guaranteed a row. A table with nosum_positioncolumn, or with it renamed, is read as a Search Console download and held to the 1,000-row rule. Rows that repeat an address are added together, as Google says to, and the page says how many addresses repeat.sum_positionis not a position (it is zero-based and summed), and this tool does not use it. - The lowest pages
- Every page with a row, ranked by clicks (impressions when the table has no clicks column), then by impressions, then by address. The page lists the lowest 50; the CSV has all of them.
- Warnings that are judgement calls
- An export that states a range shorter than 365 days is warned about (a year covers every season once; this is a judgement, not Google’s number). When fewer than 50% of the export’s pages are found in the inventory, a warning says the two probably describe different hosts or sections. Both only warn; neither changes a list.
- The review CSV
- One header, then every page with a row, lowest first, then every inventory address with no row (when that list is given). A cell that would start with
=,+,-,@, a tab or a carriage return gets a leading apostrophe, so a spreadsheet does not run it as a formula. The file is plain UTF-8 with no byte-order mark; to open it in Excel with non-ASCII addresses intact, use Data > From Text/CSV and choose UTF-8.
Where the facts about Google come from
Each statement about Google on this page was read on 21 Oct 2026 from one of these pages, which Google can change.
- Export truncated to 1,000 rows, totals are actual totals, ~ and - are zeros: support.google.com/webmasters/answer/12919797
- The table shows at most 1,000 rows: support.google.com/webmasters/answer/17010575
- Canonical URL aggregation, and the Pages dimension as the final URL after redirects: support.google.com/webmasters/answer/17011259
- A page with a noindex rule is dropped from search results: developers.google.com/search/docs/crawling-indexing/block-indexing
- A bulk export holds all the performance data available for the property except anonymized queries: support.google.com/webmasters/answer/12918484
- The columns of
searchdata_url_impression, repeated keys, andsum_positionas a zero-based sum: support.google.com/webmasters/answer/12917991 - The first export includes the day of the export, and earlier days come from the API or the reports: support.google.com/webmasters/answer/12917675
- Google’s sample queries for the export, which end in
LIMIT 1000: support.google.com/webmasters/answer/12917174 - Sitemap limits, sitemap indexes and text sitemaps: developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap
- Search Console shows up to 16 months (the post of 8 Jan 2018 says “you’ll have 16 months of data”; read 21 Oct 2026): developers.google.com/search/blog/2018/01/introducing-new-search-console