ScreenshotNeo

BlogHow-to

How to Capture Search Result Screenshots Before and After a Site Migration

Create repeatable screenshots of Google results before and after a migration, then use Search Console to investigate changes without mistaking one search for a ranking report.

By the ScreenshotNeo team4 October 202612 min read

To capture search results before and after a site migration, save screenshots of the actual Google Search results page for the same queries, using the same recorded search context each time. Record the date and time, location, language, device and viewport, browser, and signed-in or clean-profile state. After launch, repeat the captures and compare the visible URLs, titles, snippets, and result layout. Use Search Console to investigate indexing and traffic trends; a screenshot is evidence of one observed search page, not proof that a migration succeeded or a definitive ranking measurement.

Search results vary by time, place, device, and recent search history. Keeping conditions consistent makes captures more useful, but does not make them universal or perfectly repeatable. Google explains this variability in its Performance report documentation.

1. Decide what to capture

Build a short list of queries tied to migration risk and business impact. Keep the query text exactly as searched, including punctuation and spacing. Include a manageable sample rather than trying to archive every possible search.

  • Brand and site name: Check whether branded results point to the expected domain and canonical pages.
  • Important products, services, or categories: Choose queries that should surface key landing pages.
  • Queries associated with URLs that are changing: These help you observe whether a new URL appears and whether an old URL remains visible.
  • Representative non-brand searches: Include a few queries that matter for discovery beyond people already looking for your organization.

For each query, define the intended page or pages after migration. That gives the reviewer something specific to look for without treating one search result as a complete measure of visibility.

2. Record a comparable search context

Use a capture log. Fill it in before launch and reuse its fields after launch. If you cannot reproduce a condition exactly, record what changed.

Field What to record Why it matters
Query Exact text submitted to Google Small wording changes can return different pages.
Capture time UTC date and time for the screenshot Results can change over time; timestamps order the evidence.
Location Country and, when relevant, city or configured location Search results are location-sensitive.
Language Browser or search language setting used Language settings can affect the page and results.
Device and viewport Desktop or mobile, viewport width and height, and device emulation if used The visible layout and result set can differ by device.
Browser Browser name and version where available Rendering and automation behavior can differ.
Profile state Signed in or out; clean profile or established profile Recent search history and account context can affect results.
Capture notes Unexpected prompts, consent screens, CAPTCHA, errors, or changed conditions These explain why two images may not be comparable.

A clean browser profile can reduce variation from account and history when practical. Do not claim that it removes personalization completely. Avoid signing into a personal account in an automated job unless the workflow specifically requires it and the profile is handled securely.

3. Capture the actual Google results page

Open Google Search in the browser and capture the results page itself. Search Console URL Inspection can show how Google renders a page on your site, including a screenshot after a successful live test; that is a rendered site page, not a screenshot of Google Search results. See the URL Inspection documentation.

A viewport screenshot is usually the clearest record of the initial result layout. If an important result is below the fold, take additional screenshots at recorded scroll positions or a full-page screenshot. A full-page image is useful for archiving, but may compress the visible hierarchy when reviewed at normal size.

File naming and evidence log

Use stable, sortable filenames that include a query identifier and UTC timestamp, for example:

before_brand-query_2026-10-01T14-30-00Z_desktop.png
after_brand-query_2026-10-15T14-30-00Z_desktop.png

Keep the exact query and full context in a CSV, spreadsheet, or JSON sidecar. Do not put sensitive account details or session tokens in filenames. Preserve the original screenshots; if you crop, annotate, or create a diff, save it as a separate derived file.

4. Automate repeat captures with Playwright

Playwright can set a viewport, navigate to a search URL, and save a screenshot. This Node.js example takes a query from the command line, writes a timestamped PNG, and prints the capture metadata for a log. Google may show a consent interstitial, CAPTCHA, or other challenge; the script records what the browser rendered and does not attempt to bypass access controls.

npm init -y
npm install playwright
npx playwright install chromium

Save this as capture-serp.mjs:

import { chromium } from 'playwright';
import { mkdir } from 'node:fs/promises';

const query = process.argv.slice(2).join(' ').trim();
if (!query) {
  console.error('Usage: node capture-serp.mjs "your search query"');
  process.exit(2);
}

const locationLabel = process.env.CAPTURE_LOCATION ?? 'unspecified';
const language = process.env.CAPTURE_LANGUAGE ?? 'en';
const width = Number(process.env.VIEWPORT_WIDTH ?? 1365);
const height = Number(process.env.VIEWPORT_HEIGHT ?? 900);
if (!Number.isInteger(width) || !Number.isInteger(height) || width < 320 || height < 320) {
  throw new Error('Viewport width and height must be integers of at least 320 pixels.');
}

const now = new Date();
const stamp = now.toISOString().replaceAll(':', '-').replaceAll('.', '-');
const slug = query.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 60) || 'query';
const outputDir = 'serp-captures';
await mkdir(outputDir, { recursive: true });
const path = `${outputDir}/${stamp}_${slug}_${width}x${height}.png`;

const browser = await chromium.launch({ headless: true });
try {
  const context = await browser.newContext({
    viewport: { width, height },
    locale: language,
    colorScheme: 'light'
  });
  const page = await context.newPage();
  const searchUrl = new URL('https://www.google.com/search');
  searchUrl.searchParams.set('q', query);
  searchUrl.searchParams.set('hl', language);

  const response = await page.goto(searchUrl.toString(), {
    waitUntil: 'domcontentloaded',
    timeout: 60000
  });
  await page.waitForTimeout(2000);
  await page.screenshot({ path, fullPage: false });

  console.log(JSON.stringify({
    query,
    capturedAtUtc: now.toISOString(),
    location: locationLabel,
    language,
    viewport: `${width}x${height}`,
    browser: 'Chromium (Playwright)',
    profile: 'new, unsigned context',
    httpStatus: response?.status() ?? null,
    finalUrl: page.url(),
    title: await page.title(),
    screenshot: path
  }, null, 2));
  await context.close();
} finally {
  await browser.close();
}

Run it with a query. Set the optional environment variables to make the log explicit; a language setting does not guarantee a particular physical location. The example creates a fresh unsigned context per run, so it does not preserve cookies or history between captures.

CAPTURE_LOCATION="United States, New York" CAPTURE_LANGUAGE="en" \
VIEWPORT_WIDTH=1365 VIEWPORT_HEIGHT=900 \
node capture-serp.mjs "example product category"

To emulate a mobile viewport, use a smaller width and height, such as VIEWPORT_WIDTH=390 VIEWPORT_HEIGHT=844. This changes the browser viewport; it does not reproduce every property of a physical phone or guarantee results from a particular mobile user.

Automation choices that affect repeatability

  • Viewport screenshot or full page: Use a viewport image for the initial visible layout. Capture below-the-fold results separately, or use Playwright’s fullPage: true when you want an entire scrollable page archive. Full-page captures can be very tall.
  • Wait condition: The sample waits for DOM content and then a short fixed delay. A fixed delay is simple but may be too short or longer than necessary. If a page is still changing, wait for a visible landmark and record the condition. Avoid relying on network idle for pages with persistent network activity.
  • Browser and execution environment: Keep the Playwright version, browser build, operating system, fonts, viewport, and headless setting stable. Playwright warns that rendering can vary across OS, browser version, settings, hardware, power conditions, and headless mode. Read its visual comparison guidance.
  • Consent and challenges: If a consent page or challenge appears, save it and mark the run as interrupted or non-comparable. Do not interpret it as an organic result page.
  • Location: A locale or query parameter is not equivalent to controlling the searcher’s geographic location. Record the actual location context and use a consistent method across both periods.

5. Repeat the capture after launch and review it

  1. Run the same exact query list after launch.
  2. Use the same browser setup, viewport, language, location method, and profile state as the baseline where possible.
  3. Save each screenshot with a new UTC timestamp and preserve the capture metadata.
  4. Note unavoidable changes, such as a different browser build, a consent interstitial, an unavailable location setting, or a changed account state.
  5. Compare the page manually or create a visual diff as an aid. Check the expected new URL, any old URL that remains, visible title and snippet, and major result layout changes.
  6. Record observations separately from conclusions. For example: “The new product URL was visible in this capture” is an observation. “The migration is complete” requires more evidence.

Pixel diffs can flag changes in ads, dates, fonts, or layout as well as changes in organic listings. Review the images before treating a diff as meaningful. Playwright’s screenshot comparison is intended for visual comparison, but its documentation notes environmental variation; keep the capture environment stable and inspect differences.

A SERP screenshot records one observed page. Search Console provides different evidence:

  • Performance report: Compare date ranges and filter by query, page, country, device, and search type. Review clicks, impressions, click-through rate, and average position. The report supports filters and dimensions, but its aggregated metrics are not a visual record of an individual search session. Google’s Performance report guide describes the metrics and filters.
  • URL Inspection: Inspect a specific new or missing URL to see indexed information, then run a live test when appropriate. Indexed data and live-test results answer different questions. A live-test screenshot is how Google-InspectionTool sees the site page, not the Google Search results page. The live test does not replace the indexed record.
  • Migration configuration: Choose Search Console migration actions based on what changed. A domain or subdomain move may qualify for Change of Address after the move and redirects are in place. HTTP-to-HTTPS moves, same-domain host changes such as www to non-www, path moves, and hosting changes with no visible URL change are not reasons to submit that tool; follow the relevant URL-change or no-URL-change guidance instead. See Change of Address requirements, Google’s URL-changing site move guide, and its no-URL-change guide.

For an eligible domain move, verify old and new properties, implement and test redirects, and submit Change of Address for the old site after the move. Google says the action lasts 180 days and recommends keeping redirects for at least 180 days; longer may be appropriate while Search traffic still arrives through them. Google also gives general guidance that most pages on a small or medium site may take a few weeks to move, while larger sites can take longer. Treat that as general guidance, not a deadline for an individual migration. Details are in the Change of Address help page and site move documentation.

7. Troubleshooting common problems

Problem Likely cause What to do
The screenshot shows consent, CAPTCHA, or an unusual interstitial The search page did not reach the ordinary results view, or access requires an interaction. Keep the screenshot as evidence, label the run as challenged or interrupted, and capture again later through an allowed normal browser session. Do not count it as a comparable SERP capture.
The before and after images look very different even though the query is the same Location, device, viewport, language, browser, signed-in state, history, or capture time changed. Compare the metadata first. Repeat under the closest reproducible context and annotate differences that cannot be controlled.
Expected results are below the fold The viewport shows only the initial screen. Capture additional scroll positions or use a full-page image, keeping the viewport and scroll position documented.
The Playwright script times out on navigation The page was slow, a challenge intervened, or navigation did not reach the selected condition before the timeout. Inspect the final browser state, check connectivity, and adjust the timeout or wait strategy. Save and label a partial/interrupted run rather than assuming the page loaded correctly.
Cannot find package 'playwright' The package is not installed in the current project or the script is run from another directory. Run npm install playwright in the project directory, then run the script there.
Browser executable is missing Playwright’s Chromium binary has not been installed for the environment. Run npx playwright install chromium; in a managed Linux image, install the required browser dependencies as well.
Playwright cannot launch in a container or CI job The environment may lack browser system dependencies or appropriate runtime configuration. Use a supported Playwright environment, install its browser dependencies, and keep the same image for baseline and later captures.
Search Console metrics disagree with a screenshot A screenshot is one query/session, while the report aggregates data over selected dates and dimensions; results vary by context. Check the selected property, date range, search type, query/page filters, and device/country dimensions. Use repeated captures as visual samples and the report for trends.
URL Inspection shows a rendered page but not the result listing URL Inspection renders a site URL for Google’s inspection tool; it is not Google Search. Capture the search results page in a browser separately. Use URL Inspection to diagnose the individual page’s indexing and live-test state.

8. Performance, reliability, and cost

  • Keep the query set small and purposeful. More captures create more files and review work. Prioritize high-value queries and pages, then expand if Search Console trends identify a problem.
  • Schedule captures at comparable times when practical. This improves the record but cannot freeze search results or guarantee identical rankings.
  • Store original files and metadata together. A PNG can be large; choose an archive and retention approach appropriate to your evidence needs. Preserve timestamps and avoid silently replacing the baseline.
  • Plan for partial failures. Browser launches, navigation, and search access can fail independently. Log the status and final URL, save diagnostics where appropriate, and retry interrupted captures without overwriting the first attempt.
  • Treat screenshots as potentially sensitive operational records. Review what browser profile and on-screen information are captured, restrict access to the archive, and set a retention period that fits your process.
  • Cost depends on the capture approach. A local Playwright job uses your compute and storage, and requires maintaining a browser environment. A screenshot API can remove browser setup and charge according to its own plan and billing rules; review the provider’s documentation and pricing before scaling a capture set.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. For a captured Google results page, send the search URL as the target URL; keep the same query and capture context in your own log before and after the migration. One GET request returns an image or PDF. Read the ScreenshotNeo API documentation for request options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url="https://www.google.com/search?q=example+product+category" -o serp.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={
        "access_key": "YOUR_API_KEY",
        "url": "https://www.google.com/search?q=example+product+category",
    },
    timeout=90,
)
r.raise_for_status()
open("serp.webp", "wb").write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://www.google.com/search?q=example+product+category'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('serp.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. As with any automated search capture, record the query and capture context and verify that the returned page is the intended results page.

Sign up for 1,000 free screenshots a month, with no card required.

FAQ

Does a SERP screenshot prove that the migration worked?

No. It records one observed search page. Combine repeated observations with redirects, URL Inspection, and Search Console performance trends.

No. URL Inspection can show Google’s rendered view of a page on your site. Capture Google Search itself in a browser when you need a SERP record.

How long should I keep redirects after a domain move?

Google recommends at least 180 days. Keep them longer when Search traffic still arrives through them; see the linked Change of Address guidance.

Timing varies. Google’s general guidance is a few weeks for most pages on a small or medium site, with larger sites taking longer. Do not use that estimate as a deadline for an individual site.

Can I compare screenshots pixel by pixel?

You can, but interpret diffs carefully. Browser rendering and changing result-page elements can create differences unrelated to the migrated listing.