Verify a fix
Recheck a fix task's URLs in seconds after you deploy. What is rechecked, what it costs, the limits, and what each result means.
After you deploy a fix, Verify fix re-fetches only the task's affected URLs (up to 200) and runs the same checks again. It costs 1 credit per URL fetched, needs a verified site, and usually finishes in seconds. When every rechecked URL passes, the task is marked fixed. In the app: the "Verify fix" button on any task in the Top 3 or on the tasks page. Agents: verify_fix (MCP) or POST /v1/sites/{id}/recheck.
Requirements and limits
| Item | Value |
|---|---|
| Site | Ownership must be verified (see Verify site ownership). Otherwise the button reads "Verify ownership to recheck" and the API answers 409 site_not_verified. |
| URLs per recheck | 1–200. A task with more than 200 affected pages is sampled: the 200 with the most Search Console clicks, then URL order. |
| Cost | 1 credit per URL. Credits for all URLs are reserved up front; you are charged per URL actually fetched and the rest is refunded. |
| Rate | 30 rechecks per hour per team. A recheck refused for insufficient credits does not count. |
| Crawl speed | At most 2 requests per second, or your site's own lower speed setting. |
| Time | At most 120 seconds of fetching. URLs not reached by then are not_checked. |
| Task type | Only tasks with recheckable: true. See the table below. |
What a recheck checks
A recheck fetches each URL once, with the same crawler and user agent as a full audit, and does not follow links. It re-evaluates:
- the URL's response:
BROKEN_PAGE,SERVER_ERROR,FETCH_FAILED,PRIVATE_ADDRESS_SKIPPED,BLOCKED_BY_FIREWALL; - every on-page check of an HTML page (title, meta description, headings, canonical presence, Open Graph, images, mixed content, JavaScript redirects, size, response time, structured data);
- duplicates (
DUPLICATE_CONTENT,DUPLICATE_TITLE,DUPLICATE_META_DESCRIPTION): each rechecked page is compared with the other rechecked pages and with the rest of the site's latest full audit (the "duplicate baseline").
It does not re-evaluate anything that depends on the whole site: internal link graph, sitemap, orphan pages, robots.txt, canonical and redirect targets, hreflang, external links, AI and performance samples, and changes between audits. Those tasks show recheckable: false; the app shows "Re-verified at the next full audit" instead of the button, and the API answers 422 cannot_verify. Run a full audit after fixing them.
Recheckable check codes
| Group | Codes |
|---|---|
| Response | BROKEN_PAGE, SERVER_ERROR, FETCH_FAILED, PRIVATE_ADDRESS_SKIPPED, BLOCKED_BY_FIREWALL |
| Titles and descriptions | TITLE_MISSING, TITLE_TOO_LONG, TITLE_TOO_SHORT, MULTIPLE_TITLE_TAGS, META_DESCRIPTION_MISSING, META_DESCRIPTION_TOO_LONG, META_DESCRIPTION_TOO_SHORT, MULTIPLE_META_DESCRIPTIONS |
| Content | H1_MISSING, MULTIPLE_H1, THIN_CONTENT, IMAGES_MISSING_ALT, STRUCTURED_DATA_INVALID |
| Head tags and links | CANONICAL_MISSING, NOINDEX_PAGE, OG_TAGS_MISSING, OG_TAGS_INCOMPLETE, OG_URL_MISMATCH, HTTP_LINK_ON_HTTPS, MIXED_CONTENT, JS_REDIRECT |
| Performance | PAGE_TOO_LARGE, SLOW_PAGE |
| Duplicates | DUPLICATE_CONTENT, DUPLICATE_TITLE, DUPLICATE_META_DESCRIPTION |
Every other check code, and every INDEX_* Google triage task, is not recheckable. The issue reference marks each code.
Results
Per task
result |
Meaning | Task status after |
|---|---|---|
fixed |
Every rechecked URL was checked and none has the issue. | fixed |
still_failing |
At least one URL still has the issue. | open |
not_checked |
Nothing failed, but some URL could not be checked. | open |
cannot_verify |
A recheck can't judge this code, or a duplicate check had no baseline (the latest full audit's data was unavailable). | open |
Each task result also has urls_failing, urls_passing, urls_rechecked, pages, sampled and covers_task. A fixed result records a fix event, which Traffic from fixes measures.
Per URL
result |
Meaning | App label |
|---|---|---|
fixed |
The task's issue is gone. | Fixed |
still_failing |
The task's issue is still there. | Still failing |
new_issue |
The task's issue is gone, but errors or warnings appeared that the latest audit did not have on this URL (listed in new_issues). The task still counts as passing on this URL. |
New issue |
not_checked |
The URL could not be judged; see reason. |
Not checked |
cannot_verify |
The URL's only task codes are ones a recheck can't verify. | Needs a full audit |
passing |
A URL you passed that has no task on it, and no errors. | Passing |
not_checked reasons:
reason |
Meaning |
|---|---|
not_fetched |
Not reached (for example the 120-second limit). |
blocked |
A firewall or bot challenge answered instead of your page. |
fetch_error |
The request failed (DNS, TLS, timeout). |
status_<code> |
The URL answered that status, e.g. status_503, or status_404 for an on-page check, which only runs on a 200 HTML answer. |
not_html |
The URL answered 200 but not text/html, so on-page checks did not run. |
A URL that now answers a 3xx redirect passes its on-page checks and is reported with redirected: true and redirect_to.
In the app the result line reads "N of M pages pass", with a heading of "Fixed", "Still failing", "Couldn't check every page", "Re-verified at the next full audit" or "The recheck didn't finish". "Verify again" starts a new recheck.
Rechecking your own list of URLs
Instead of a task, you can pass 1–200 URLs. Each must be an http(s) URL on the site's host (with or without www), or the API answers 422 invalid_urls. SEOFix finds the tasks those URLs belong to in the latest full audit. A task's status changes only when your list covers every one of its affected pages; otherwise you get per-URL results without changing task status.
For agents
curl -s -X POST "https://api.seofix.ai/v1/sites/42/recheck" \
-H "Authorization: Bearer $SEOFIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"task_key": "3f9c2a71b0d4e8a6"}'
Send either task_key (16 hex characters) or urls (an array of 1–200 strings), not both. The answer is 202:
{
"recheck_id": 9188,
"status": "queued",
"urls_total": 200,
"estimated_credits": 200,
"sampled": true,
"tasks": [
{"task_key": "3f9c2a71b0d4e8a6", "code": "TITLE_TOO_LONG", "template": "/jobs/[slug]",
"urls_rechecked": 200, "pages": 1840, "sampled": true, "covers_task": true, "result": null}
]
}
Poll GET /v1/rechecks/{recheck_id} until status is done, failed or cancelled:
{
"recheck_id": 9188,
"status": "done",
"urls_total": 200,
"pages_crawled": 200,
"time_capped": false,
"duplicate_baseline": 9120,
"urls": [
{"url": "https://example.com/jobs/senior-accountant-dubai", "status_code": 200,
"result": "fixed", "reason": null, "redirected": false, "redirect_to": null,
"issues": [], "new_issues": []}
],
"tasks": [
{"task_key": "3f9c2a71b0d4e8a6", "code": "TITLE_TOO_LONG", "result": "fixed",
"urls_failing": 0, "urls_passing": 200, "status": "fixed"}
]
}
MCP: verify_fix takes site_id and task_key (or urls), starts the recheck, polls for up to 60 seconds and returns the results. If the recheck is still running it returns {recheck_id, status: "running"}; call get_recheck with that id later instead of starting another recheck.
Errors:
| HTTP | error.code |
Meaning |
|---|---|---|
| 402 | insufficient_credits |
Not enough credits for the URLs. |
| 404 | not_found |
No task with this key in the site's latest audit. |
| 409 | site_not_verified |
Verify site ownership first. |
| 422 | cannot_verify |
The task's code needs a full audit (or Google, for INDEX_* tasks). |
| 422 | invalid_urls |
A URL is not on the site's host, or the list is empty or over 200. |
| 429 | recheck_rate_limited |
More than 30 rechecks this hour; see the Retry-After header. |
| 503 | dispatch_failed |
The recheck could not be queued; try again. |
Related
More in Fixes
Still stuck? Email [email protected] with your site and what you expected to see.