Free tool · no account · runs in your browser

Search Console history merger

Search Console shows up to 16 months of performance data. Export it every so often, drop every daily export here together, and get one deduplicated daily CSV that keeps going back as far as your exports do. Where two exports disagree you see the day, both values and which one was kept; where no export has a day, you see the gap.

Your files never leave your browser. They are read by JavaScript in this tab; there is no upload, and this page's security policy blocks fetch, XHR, WebSocket, EventSource and beacon calls and form posts.

Choose them all at once (Ctrl or Shift click), or drop them here. The ZIP from the Export button, or its daily file: Dates.csv, or Chart.csv in newer exports. A file that is not a daily table is named and left out.

What it does

One series, with every choice on show

A rule for which value wins

When two exports hold the same day, the value comes from an export in which that day is not among its last 3 days, which may still have been preliminary. If that does not settle it, the export whose range ends latest wins. A row's clicks, impressions, CTR and position always come from one export.

Conflicts and gaps, never smoothed

A difference beyond rounding is listed with every export's value and the reason for the one kept. A day no export holds is listed as a gap and is not filled in, because a day with no row is not a day with no traffic.

Search Console's own layout

The download is a Dates-style CSV, one row per day, so it can be uploaded here again next time with the newest export, and Penlid's other tools read it.

What to upload, and how often

Daily exports of the same property, taken with the same filters. In Search Console, open Performance, then Search results, choose the longest range on offer, and use Export, then Download CSV. Repeat that every few months and keep the ZIPs. Google's January 2018 launch post for the new Search Console says "you'll have 16 months of data"; Search Console shows up to 16 months, so an export from today reaches back that far and no further.

Why not Google's own bulk export? It is a good way to keep data from now on: Google's page for it says the data accumulates in your BigQuery project unless you set an expiry. It starts on the day you set it up, and for data from before that Google points you to the Search Console API or the reports. A set of exports is the way to keep what you can still reach today without setting up Google Cloud.

A weekly or monthly table, a table taken with Compare, and a table of pages by day are named and left out: they are not a daily series for the whole site. The ZIP's Filters.csv is read, and exports taken under different filters (a different search type, country, device or page filter) are refused, because merging them would put two populations of traffic into one series. An export does not say which property it came from, so check that yourself.

One row per day. The merged file holds the whole site's clicks, impressions, CTR and average position for each day. It does not hold pages or queries.

What a merge can and cannot do

  • It cannot recover a day you never exported. The exports have to cover the days. A gap in the result is a gap in what you kept, and it is listed with its dates.
  • Preliminary days. Google says the newest data can be preliminary and that collected data is usually available in two to three days. A file does not record when it was exported, so the last 3 days of every export are treated as possibly preliminary, whatever the real date was. When you merge again next time, the newer export's value for those days wins.
  • Rounding. Clicks and impressions are whole numbers Google reports exactly, so any difference between two exports is a conflict. CTR and average position are written to a decimal or two, so differences up to 0.05 percentage points of CTR and 0.05 of position are rounding and not conflicts.
  • Google's own corrections. Google says impressions were not accurately reported from 13 May 2025 to 27 Apr 2026 and that, now it is fixed, impressions may read lower. Two exports taken either side of that fix will disagree on impressions for those days; the merge says so beside the conflicts, and keeps the later export's value, which is the one after the fix.
  • The wrong exports. When more than a quarter of the settled days two exports share have different clicks, nothing is merged: that is more disagreement than this tool allows between exports of one property under one filter, and a different property, country, device or page filter would explain it. Impressions are not used for that test, because of the correction above.
  • Pacific Time. Dates in an export are Pacific Time in every view except the 24-hour view, and the merged file keeps them as they are.

Keeping it without remembering

Penlid’s plans are built to archive your regular Search Console performance data past the 16 months Search Console shows, once you connect it. That connection only starts once Google sign-in has been configured on the deployment (see the features page), so check before relying on it: what each plan includes.

What happens to your files

Nothing leaves your browser. The files 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.

You do not have to take our word for it. Open your browser's developer tools, choose the Network tab, run a merge, 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 two things that do leave this page's memory are the two you ask for: the merged CSV you click to download, and the summary you click to copy.

Methods: the rules and thresholds

Each number below is a constant in public/assets/lib/series-tools.js. The project's tests compare the numbers quoted here with those constants. They are judgement calls, and they are the owner's to change.

Reading the files
At most 40 files are merged at once; more is refused, and the page says to merge in two rounds. A table is recognised by its columns, not its name. A daily table has a date column and both clicks and impressions. A day that appears more than once inside one file is left out of that file, not added up. A row with a negative or fractional count is not used, and is named. Blank clicks or impressions cells that the parser read as 0 are named, because a zero put into an archive is a data point.
Which value wins
For a day held by several exports: first, an export in which the day is not among its last 3 days (the file's newest days, treated as possibly preliminary); then the export whose range ends latest; then the file chosen first. The whole row is taken from the winner.
A conflict
Any difference in clicks or impressions (tolerance 0), a difference in CTR of more than 0.05 percentage points, or in average position of more than 0.05. A conflict is listed with each export's values, the export kept, and why. A conflict that falls inside Google's listed period for a documented data anomaly that affects that figure is named with it.
When nothing is merged
When the exports' Filters files differ in search type or in any filter other than the dates; and when the exports share at least 7 settled days (days that are not among the last 3 of any export holding them) and more than 25% of those days have different clicks.
Gaps
Every run of days between the first and the last that no export holds. They are listed, never filled, and the CSV simply has no row for them.
The CSV
Header, then one row per day: Date, Clicks, Impressions, and CTR (as a percentage) and Position where any export had them, with those cells left blank for a row whose export lacked them. Plain UTF-8, no byte-order mark, LF line ends. The months figure is the span of days divided by 30.44, a label, not a calendar count.
Months Search Console shows
The page counts days before the date 16 months before today (Pacific Time) and says those days could not be exported again. Google says Search Console shows up to 16 months; it does not say what it does with older data, and this tool does not either.