OnPage.dev

Free hosted SEO and AI-visibility scanner for agents: scan, fix, verify, redirects, robots.txt.

¿Debería usar esto?

Calidad y seguridad

B
Calidad de la descripción
99%
Integridad del esquema
96%
Calidad de los nombres
92%
Riesgo de envenenamiento
0%
Coincidencia de permisos
100%
Cumplimiento del protocolo
100%

Hallazgos (8)

  • HIGHTool poisoning patterns detected
  • MEDIUMTool 'generate_schema' description contains placeholder texten generate_schema
  • MEDIUMTool 'check_entity_graph' description contains placeholder texten check_entity_graph
  • MEDIUMTool description contains URL to non-standard domainen generate_llms_txt
  • MEDIUMTool description contains URL to non-standard domainen check_og_tags
  • LOWTool description contains role marker that could confuse chat modelsen watch_page
  • INFOTool description contains placeholder or incomplete texten generate_schema
  • INFOTool description contains placeholder or incomplete texten check_entity_graph

Basado en el análisis automatizado de las definiciones de herramientas y el cumplimiento del protocolo.

Costo de contexto

~10,441Tokens (definiciones de herramientas)
~1.6 KBTamaño de respuesta típico
Impacto significativo en la atención (8.16% del contexto de 128k)

Este es el número aproximado de tokens que se consumen cada vez que las herramientas del servidor se cargan en el contexto de un modelo. Los recuentos más altos reducen la atención disponible para otras tareas.

Instalar

Instalación con un clic

Agrega esto a tu archivo `claude_desktop_config.json`:

{
  "mcpServers": {
    "onpage": {
      "url": "https://onpage.dev/mcp"
    }
  }
}

Puntos de conexión remotos

https://onpage.dev/mcpstreamable-http

Qué puede hacer

Inventario de herramientas

Herramientas (39)

🟢 Solo lectura🟡 Escritura🔴 Eliminación⚪ Desconocido
🟢scan_page(url)

Scan one public web page for SEO and AI visibility. Returns a 0-100 score, the issues to fix first with why and how, AI readiness, and the key facts (title, description, headings, words, speed, structured data). Use this first for any question about how a page performs in Google or AI search.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address of the page, for example https://example.com/pricing. A bare domain like example.com also works."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}
🟢check_ai_visibility(url)

Check whether ChatGPT, Claude, Perplexity, Gemini and other AI crawlers may read a page (robots.txt per bot), whether llms.txt exists, how ready and citable the content is for AI answers (14 checks, including fact density, cited outside sources and whether question headings get a direct answer), and how an AI model sees the page as plain text. Use this for questions like 'why does ChatGPT not mention my site'.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address of the page, for example https://example.com/pricing. A bare domain like example.com also works."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}
🟢check_focus_keyword(url, keyword)

Check how well a page targets one search term: title, meta description, H1, URL, first 100 words, subheadings, image alt texts and keyword density (flags stuffing over 3%). Returns 8 checks with a tip each.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address of the page, for example https://example.com/pricing. A bare domain like example.com also works."
    },
    "keyword": {
      "type": "string",
      "description": "The search term the page should rank for, for example 'running shoes'."
    }
  },
  "required": [
    "url",
    "keyword"
  ],
  "additionalProperties": false
}
🟢get_fix_pack(url, platform)

Generate ready-to-paste fixes for the issues on a page, built from the page's own content: a title tag, meta description, canonical, social (Open Graph) tags, viewport and a JSON-LD starting point. Only issues the page actually has are included. With platform wordpress it returns a WordPress plan instead: the exact Yoast SEO or Rank Math field for each value, alt texts for the media library, and the steps to ship it through the user's own WordPress connection (for example a WordPress MCP server) after the user approves each change.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address of the page, for example https://example.com/pricing. A bare domain like example.com also works."
    },
    "platform": {
      "type": "string",
      "enum": [
        "html",
        "wordpress"
      ],
      "description": "html (default) for code to paste, wordpress for a plan your WordPress connection can apply."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}
🟢scan_html(html, url)

Scan raw HTML that is not published yet, for example a local build, a template or a draft from your editor. Returns the same score, fixes and AI readiness as scan_page. Pass the full HTML document; url is optional and only used to resolve relative links. Use this in coding assistants to check SEO before deploying.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "html": {
      "type": "string",
      "description": "The complete HTML document, up to 900 KB."
    },
    "url": {
      "type": "string",
      "description": "Optional address the page will live at, used for relative links and the canonical check."
    }
  },
  "required": [
    "html"
  ],
  "additionalProperties": false
}
🟢rescan_and_compare(url)

Scan a live page again and compare it with the previous scan of that page: score change, issues fixed, new issues and AI readiness change. Use this after deploying fixes to confirm they worked, or to catch regressions such as a robots.txt change that suddenly blocks AI crawlers. Repeat until the score is where you want it.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address of the page, for example https://example.com/pricing. A bare domain also works."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}
🟢check_snippet(title, description)

Estimate how a title and meta description show in Google: pixel width against the cut-off on desktop and mobile, and the truncated text a searcher would see. No network call. Use it to iterate on title and description variants until they fit.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "description": "Proposed title tag text."
    },
    "description": {
      "type": "string",
      "description": "Proposed meta description."
    }
  },
  "required": [
    "title"
  ],
  "additionalProperties": false
}
🟢generate_schema(url, type)

Generate a JSON-LD block for a page from its own content and validate it against Google's rich result rules. Types: Article, Product, FAQPage (built from question headings and their answers), Organization (with sameAs links found on the page), BreadcrumbList (from the URL), or auto to pick the best fit. Values that cannot be read from the page are marked TODO.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address of the page, for example https://example.com/pricing. A bare domain also works."
    },
    "type": {
      "type": "string",
      "enum": [
        "auto",
        "Article",
        "Product",
        "FAQPage",
        "Organization",
        "BreadcrumbList"
      ],
      "description": "Schema type, default auto."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}
🟢find_answer_passages(url, question)

Find the passages on a page that best answer a given question, the way AI answer engines pick text to quote. Returns the top passages with their heading, word count and whether they are a quotable length (40 to 90 words). Use the result to judge whether the page answers the question well, and to rewrite the best passage into a direct answer.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address of the page, for example https://example.com/pricing. A bare domain also works."
    },
    "question": {
      "type": "string",
      "description": "The question people ask, for example 'how long does shipping take to Germany'."
    }
  },
  "required": [
    "url",
    "question"
  ],
  "additionalProperties": false
}
🟢generate_llms_txt(url)

Build a ready-to-upload llms.txt for a site from its sitemap and home page: site name, summary and the main pages grouped by section. Upload the result to the root of the site, for example https://example.com/llms.txt.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Home page of the site, for example https://example.com."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}
🟢ai_crawler_policy(url, policy)

Write robots.txt rules for AI crawlers based on a policy, and merge them into the site's current robots.txt. Policies: allow_all, search_only (allow AI search and user-requested fetches, block model training), block_training (same as search_only), block_all. Returns the full new robots.txt and what changes.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Any page of the site."
    },
    "policy": {
      "type": "string",
      "enum": [
        "allow_all",
        "search_only",
        "block_training",
        "block_all"
      ],
      "description": "Which AI crawlers to allow."
    }
  },
  "required": [
    "url",
    "policy"
  ],
  "additionalProperties": false
}
🟢deep_audit(url, sections)

Everything OnPage.dev measures on a page, by section: speed hints from the HTML, links and anchor texts, accessibility basics, image SEO, rich results, security headers, content (words, headings, readability, keywords) and technical facts (status, canonical, robots, redirects, hreflang). Pick sections to keep the answer short, or leave them out for all. Every issue has a stable code you can track across scans.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address of the page, for example https://example.com/pricing. A bare domain also works."
    },
    "sections": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "speed",
          "links",
          "accessibility",
          "images",
          "rich_results",
          "security",
          "content",
          "technical"
        ]
      },
      "description": "Sections to include. Default: all."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string"
    },
    "score": {
      "type": "number"
    },
    "issues": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "level": {
            "type": "string"
          },
          "issue": {
            "type": "string"
          }
        },
        "required": [
          "code",
          "level",
          "issue"
        ]
      }
    },
    "sections": {
      "type": "object"
    },
    "report": {
      "type": "string"
    }
  },
  "required": [
    "url",
    "issues",
    "sections"
  ]
}
🟢check_urls(urls, expected)

Check up to 20 URLs at once: final status code, the full redirect chain and where each one ends up. Built for site migrations, broken link sweeps and launch checks, for example 'do all old URLs 301 to the right new page?'. Pass expected targets to verify each redirect.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "urls": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "minItems": 1,
      "maxItems": 20,
      "description": "Addresses to check."
    },
    "expected": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 20,
      "description": "Optional expected final address for each URL, in the same order."
    }
  },
  "required": [
    "urls"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "results": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "status": {
            "type": [
              "number",
              "null"
            ]
          },
          "finalUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "hops": {
            "type": "number"
          },
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "url",
          "ok"
        ]
      }
    },
    "okCount": {
      "type": "number"
    }
  },
  "required": [
    "results",
    "okCount"
  ]
}
🟢test_robots(url, user_agents, robots_txt)

Test a URL against the site's live robots.txt for one or more crawlers, using Google's matching rules (most specific user-agent group, longest matching rule, Allow wins ties, * and $ wildcards). Returns allowed or blocked per crawler and the exact rule that decides it. Optionally test a proposed robots.txt instead of the live one.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address of the page, for example https://example.com/pricing. A bare domain also works."
    },
    "user_agents": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 20,
      "description": "Crawler names, for example Googlebot, GPTBot, ClaudeBot, PerplexityBot. Default: Googlebot, Bingbot and the main AI crawlers."
    },
    "robots_txt": {
      "type": "string",
      "description": "Optional robots.txt content to test instead of the live file."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string"
    },
    "source": {
      "type": "string"
    },
    "results": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "userAgent": {
            "type": "string"
          },
          "allowed": {
            "type": "boolean"
          },
          "rule": {
            "type": [
              "string",
              "null"
            ]
          },
          "group": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "userAgent",
          "allowed"
        ]
      }
    }
  },
  "required": [
    "url",
    "results"
  ]
}
🟢validate_schema(jsonld)

Validate JSON-LD you wrote before you publish it: JSON syntax, @context and @type, absolute URLs, ISO dates, and Google's required and recommended fields per rich result type. Accepts a JSON-LD object, an array, a @graph, or a full <script type="application/ld+json"> block.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "jsonld": {
      "type": "string",
      "description": "The JSON-LD as text, with or without the <script> tag."
    }
  },
  "required": [
    "jsonld"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "valid": {
      "type": "boolean"
    },
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string"
          },
          "feature": {
            "type": [
              "string",
              "null"
            ]
          },
          "eligible": {
            "type": "boolean"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "type",
          "eligible",
          "errors",
          "warnings"
        ]
      }
    }
  },
  "required": [
    "valid",
    "items"
  ]
}
🟢compare_html(before, after, url)

Compare two versions of a page's HTML, for example before and after a code change, and report what got better or worse for SEO: score, issues fixed and introduced (with stable codes), and changes to title, description, H1, canonical, robots, structured data and word count. Use it in code review to catch SEO regressions before they ship.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "before": {
      "type": "string",
      "description": "HTML before the change."
    },
    "after": {
      "type": "string",
      "description": "HTML after the change."
    },
    "url": {
      "type": "string",
      "description": "Optional address the page lives at."
    }
  },
  "required": [
    "before",
    "after"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "scoreBefore": {
      "type": "number"
    },
    "scoreAfter": {
      "type": "number"
    },
    "fixed": {
      "type": "array",
      "items": {
        "type": "object"
      }
    },
    "introduced": {
      "type": "array",
      "items": {
        "type": "object"
      }
    },
    "changes": {
      "type": "array",
      "items": {
        "type": "object"
      }
    },
    "verdict": {
      "type": "string"
    }
  },
  "required": [
    "scoreBefore",
    "scoreAfter",
    "fixed",
    "introduced",
    "changes",
    "verdict"
  ]
}
🟢start_site_audit(url, max_pages)

Start an SEO audit of a whole site (up to 25 pages from the sitemap, or from the home page links when there is no sitemap). Returns an audit_id and the first progress. Then call get_site_audit with that id until status is complete; each call scans the next few pages. The finished audit gives the issues across the site by code with the affected pages, broken pages, duplicate titles and descriptions, and orphan pages, and it powers suggest_internal_links.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address, for example https://example.com. A bare domain also works."
    },
    "max_pages": {
      "type": "integer",
      "minimum": 2,
      "maximum": 25,
      "description": "How many pages to audit, default 10, at most 25."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "auditId": {
      "type": "string"
    },
    "status": {
      "type": "string",
      "enum": [
        "running",
        "complete"
      ]
    },
    "scanned": {
      "type": "number"
    },
    "total": {
      "type": "number"
    }
  },
  "required": [
    "auditId",
    "status",
    "scanned",
    "total"
  ]
}
🟢get_site_audit(audit_id)

Continue a site audit started with start_site_audit: each call scans the next pages and reports progress. Keep calling until status is complete, then you get the site-wide results. Audits are kept for one hour.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "audit_id": {
      "type": "string",
      "description": "The id returned by start_site_audit."
    }
  },
  "required": [
    "audit_id"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "auditId": {
      "type": "string"
    },
    "status": {
      "type": "string",
      "enum": [
        "running",
        "complete"
      ]
    },
    "scanned": {
      "type": "number"
    },
    "total": {
      "type": "number"
    },
    "averageScore": {
      "type": [
        "number",
        "null"
      ]
    },
    "issues": {
      "type": "array",
      "items": {
        "type": "object"
      }
    },
    "pages": {
      "type": "array",
      "items": {
        "type": "object"
      }
    }
  },
  "required": [
    "auditId",
    "status",
    "scanned",
    "total"
  ]
}
🟢suggest_internal_links(audit_id, target_url, topic)

Suggest which existing pages should link to a target page, with anchor text, based on a completed site audit. The target can be a page from the audit or a new page you are writing (give its topic). Pages that already link to the target are left out, and orphan pages are flagged. Use it when publishing new content or fixing pages that get no internal links.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "audit_id": {
      "type": "string",
      "description": "Id of a completed site audit."
    },
    "target_url": {
      "type": "string",
      "description": "Page that should receive links. Can be a new URL that is not live yet."
    },
    "topic": {
      "type": "string",
      "description": "Topic or main keyword of the target page. Needed for a new page; optional for an audited page."
    }
  },
  "required": [
    "audit_id"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "target": {
      "type": "string"
    },
    "suggestions": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string"
          },
          "anchor": {
            "type": "string"
          },
          "reason": {
            "type": "string"
          }
        },
        "required": [
          "from",
          "anchor"
        ]
      }
    }
  },
  "required": [
    "target",
    "suggestions"
  ]
}
🟢compare_pages(url, competitors, keyword)

Compare a page with up to 3 competitor pages that rank for the same search: score, AI readiness, words, headings, rich results, speed and more side by side, plus per competitor the issues to fix to catch up, structured data they have, words they use that the page does not (content gaps), facts and figures only they or only you give (information gain), and where the page is ahead. It scans one page per call and keeps results for 15 minutes, so with several new pages it asks you to call it again with the same arguments until the comparison is complete.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address, for example https://example.com. A bare domain also works."
    },
    "competitors": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "minItems": 1,
      "maxItems": 3,
      "description": "Competitor page addresses."
    },
    "keyword": {
      "type": "string",
      "description": "Optional search term to compare keyword use."
    }
  },
  "required": [
    "url",
    "competitors"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "enum": [
        "partial",
        "complete"
      ]
    },
    "rows": {
      "type": "array",
      "items": {
        "type": "object"
      }
    },
    "gaps": {
      "type": "array",
      "items": {
        "type": "object"
      }
    }
  },
  "required": [
    "status"
  ]
}
🟢prioritize_fixes(pages, source, audit_id)

Rank SEO fixes by how much traffic they can win, using data from the user's other connected tools. Before calling, look at your available tools: if Google Search Console, GA4, Ahrefs, Semrush or a similar source is connected, fetch the top pages (clicks, impressions, CTR, average position, organic traffic, referring domains) and their top queries (with position and search volume) for the site, at most 10 pages and 20 queries per page, and pass them here. Fields are optional; pass what the source has. Without traffic data it still works and ranks by severity. Pages are scanned by OnPage.dev (3 per call, kept 15 minutes); with more pages it asks you to call again with the same arguments. Pass audit_id from a finished site audit to skip rescanning. Traffic data is used for this answer only and not stored.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "pages": {
      "type": "array",
      "minItems": 1,
      "maxItems": 10,
      "items": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "clicks": {
            "type": "number",
            "minimum": 0
          },
          "impressions": {
            "type": "number",
            "minimum": 0
          },
          "ctr": {
            "type": "number",
            "minimum": 0,
            "description": "Click-through rate, 0-1 or a percentage."
          },
          "position": {
            "type": "number",
            "minimum": 0
          },
          "traffic": {
            "type": "number",
            "minimum": 0,
            "description": "Estimated monthly organic visits (Ahrefs/Semrush) or sessions (GA4)."
          },
          "backlinks": {
            "type": "number",
            "minimum": 0
          },
          "referring_domains": {
            "type": "number",
            "minimum": 0
          },
          "queries": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "object",
              "properties": {
                "query": {
                  "type": "string"
                },
                "clicks": {
                  "type": "number",
                  "minimum": 0
                },
                "impressions": {
                  "type": "number",
                  "minimum": 0
                },
                "position": {
                  "type": "number",
                  "minimum": 0
                },
                "volume": {
                  "type": "number",
                  "minimum": 0,
                  "description": "Monthly search volume."
                }
              },
              "required": [
                "query"
              ]
            }
          }
        },
        "required": [
          "url"
        ]
      }
    },
    "source": {
      "type": "string",
      "enum": [
        "gsc",
        "ga4",
        "ahrefs",
        "semrush",
        "other"
      ],
      "description": "Where the numbers come from."
    },
    "audit_id": {
      "type": "string",
      "description": "Optional id of a finished site audit, so pages are not scanned again."
    }
  },
  "required": [
    "pages"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "enum": [
        "partial",
        "complete"
      ]
    },
    "mode": {
      "type": "string",
      "enum": [
        "traffic",
        "severity"
      ]
    },
    "actions": {
      "type": "array",
      "items": {
        "type": "object"
      }
    }
  },
  "required": [
    "status"
  ]
}
🟢check_entity_graph(url)

Check how a page's structured data describes who and what it is about, the way AI knowledge graphs read it: which entities there are (Organization, Person, Article, Product), whether they link to each other by @id, whether author and publisher are real entities instead of plain text, whether sameAs points to real profiles (LinkedIn, Wikipedia, Wikidata, social) and whether those profile links load, and whether the Organization matches the one on the home page. Returns the graph, issues with stable codes and a suggested JSON-LD block with TODOs for details only the user knows.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address, for example https://example.com/blog/post. A bare domain also works."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "entities": {
      "type": "number"
    },
    "links": {
      "type": "number"
    },
    "issues": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "level": {
            "type": "string"
          },
          "issue": {
            "type": "string"
          },
          "fix": {
            "type": "string"
          }
        },
        "required": [
          "code",
          "level",
          "issue"
        ]
      }
    }
  },
  "required": [
    "entities",
    "links",
    "issues"
  ]
}
🟢validate_llms_txt(url, text)

Validate a site's llms.txt against the llmstxt.org format: served as text (not an HTML page), one H1 with the site name, a > summary, ## sections with [name](url): notes links, sensible size, and whether the linked pages load. Also checks whether llms-full.txt exists. Pass text to validate a draft before uploading it. If the site has none, use generate_llms_txt.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address, for example https://example.com/blog/post. A bare domain also works."
    },
    "text": {
      "type": "string",
      "description": "Optional llms.txt content to validate instead of the live file."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "found": {
      "type": "boolean"
    },
    "valid": {
      "type": "boolean"
    },
    "issues": {
      "type": "array",
      "items": {
        "type": "object"
      }
    },
    "sections": {
      "type": "array",
      "items": {
        "type": "object"
      }
    }
  },
  "required": [
    "found",
    "valid",
    "issues"
  ]
}
🟢compare_ai_citations(pages, source)

Compare the pages AI assistants cite with the ones they skip, using citation counts from the user's connected tools. Before calling, check your available tools: if Ahrefs with Brand Radar is connected, use its cited pages report (filter cited_domain_subdomains on the site, pass the pages to compare in tracked_urls so uncited ones come back with 0, use Ahrefs prompts) or the ai_responses_* columns of top pages; these cost API units, so ask for at most 8 pages. Any other AI-visibility source works too. Include some pages with few or no citations, so there is something to compare. OnPage.dev scans each page (one per call, kept 15 minutes; call again with the same arguments until complete) and shows which checks the cited pages pass and the others fail, and what each uncited page should change. Without citation data, use check_ai_visibility instead.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "pages": {
      "type": "array",
      "minItems": 2,
      "maxItems": 8,
      "items": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "chatgpt": {
            "type": "number",
            "minimum": 0
          },
          "perplexity": {
            "type": "number",
            "minimum": 0
          },
          "gemini": {
            "type": "number",
            "minimum": 0
          },
          "google_ai_overviews": {
            "type": "number",
            "minimum": 0
          },
          "google_ai_mode": {
            "type": "number",
            "minimum": 0
          },
          "copilot": {
            "type": "number",
            "minimum": 0
          },
          "grok": {
            "type": "number",
            "minimum": 0
          },
          "total": {
            "type": "number",
            "minimum": 0,
            "description": "Total AI citations or appearances, if the source gives one number."
          }
        },
        "required": [
          "url"
        ]
      }
    },
    "source": {
      "type": "string",
      "enum": [
        "ahrefs",
        "semrush",
        "other"
      ],
      "description": "Where the citation counts come from."
    }
  },
  "required": [
    "pages"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "enum": [
        "partial",
        "complete"
      ]
    },
    "signals": {
      "type": "array",
      "items": {
        "type": "object"
      }
    },
    "pages": {
      "type": "array",
      "items": {
        "type": "object"
      }
    }
  },
  "required": [
    "status"
  ]
}
🟡watch_page(url, webhook_url)

Start watching a page. OnPage.dev rescans it about once a day and records what changed for search and AI: the page going down or redirecting, a new noindex, AI crawlers newly blocked, a changed canonical or title, the score dropping, new errors and fixed ones. Returns a private watch_id, a private RSS feed URL the user can add to any feed reader or Slack, and optionally posts each change to an https webhook. No account needed. Use get_watch to read the history and unwatch to stop. Watches end after 90 days without a check.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address, for example https://example.com/pricing. A bare domain also works."
    },
    "webhook_url": {
      "type": "string",
      "description": "Optional https URL that receives a JSON POST when something changes, for example a Slack or Discord incoming webhook."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "watchId": {
      "type": "string"
    },
    "feed": {
      "type": "string"
    },
    "baseline": {
      "type": "object"
    }
  },
  "required": [
    "watchId",
    "feed"
  ]
}
🟢get_watch(watch_id)

Read a watch created with watch_page: the latest snapshot, when it was last checked and every change found so far, newest first.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "watch_id": {
      "type": "string"
    }
  },
  "required": [
    "watch_id"
  ],
  "additionalProperties": false
}
🔴unwatch(watch_id)

Stop a watch created with watch_page and delete its history.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "watch_id": {
      "type": "string"
    }
  },
  "required": [
    "watch_id"
  ],
  "additionalProperties": false
}
🟢create_content_brief(keyword, competitors, url, audit_id)

Build a writing brief for a search term from the pages that rank for it. Get the competitor URLs from your own search tool, Ahrefs, Semrush or the user (1 to 3). OnPage.dev scans them (one page per call, kept 15 minutes; call again with the same arguments until complete) and returns: the subtopics most of them cover, the questions they answer, figures they give that you need your own data for, terms they share, a target length, the structured data they use, title patterns, and, with an audit_id from start_site_audit, which of your pages should link to the new page. Pass url when improving an existing page to get only what it is missing.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "keyword": {
      "type": "string",
      "description": "The search term the page should rank for."
    },
    "competitors": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "minItems": 1,
      "maxItems": 3,
      "description": "Pages that rank for the term."
    },
    "url": {
      "type": "string",
      "description": "Optional: your existing page for this term."
    },
    "audit_id": {
      "type": "string",
      "description": "Optional: a finished site audit, for internal link suggestions."
    }
  },
  "required": [
    "keyword",
    "competitors"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "enum": [
        "partial",
        "complete"
      ]
    },
    "mustCover": {
      "type": "array",
      "items": {
        "type": "object"
      }
    },
    "questions": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "targetWords": {
      "type": [
        "number",
        "null"
      ]
    }
  },
  "required": [
    "status"
  ]
}
🟢plan_redirects(old_urls, old_site, new_urls, new_site, format)

Match old URLs to new ones for a site migration or restructure and write the redirect rules. Give the old URLs (a list, or the old site's address while it is still online) and the new URLs (a list, or the new site's address so OnPage.dev reads its sitemap). Each old URL gets the best new match with a confidence score, unmatched ones are flagged with a suggestion, and the rules come out ready for Cloudflare or Netlify (_redirects), nginx, Apache (.htaccess), Next.js or CSV. After going live, verify with check_urls using the new URLs as expected.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "old_urls": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 500
    },
    "old_site": {
      "type": "string",
      "description": "Old site address, to read its sitemap instead of old_urls."
    },
    "new_urls": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 500
    },
    "new_site": {
      "type": "string",
      "description": "New site address, to read its sitemap instead of new_urls."
    },
    "format": {
      "type": "string",
      "enum": [
        "redirects",
        "nginx",
        "apache",
        "nextjs",
        "csv"
      ],
      "description": "Output format, default redirects (Cloudflare Pages and Netlify)."
    }
  },
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "matched": {
      "type": "number"
    },
    "review": {
      "type": "number"
    },
    "rules": {
      "type": "string"
    }
  },
  "required": [
    "matched",
    "rules"
  ]
}
🟡share_result(url)

Scan a page again and publish a shareable proof page on onpage.dev with the score before and after, the issues fixed and the ones still open. Useful after fixing a client's site: send them the link. Uses the previous OnPage.dev scan of the page as the before; without one, it shows the current result. The page is public for anyone with the link, not indexed by search engines, and expires after 90 days.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address, for example https://example.com/pricing. A bare domain also works."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "link": {
      "type": "string"
    },
    "before": {
      "type": [
        "number",
        "null"
      ]
    },
    "after": {
      "type": "number"
    }
  },
  "required": [
    "link",
    "after"
  ]
}
🟢render_page(url)

Load a page in a real browser on a phone (390x844), tablet (820x1180) and desktop (1440x900) and check the first screen: is the H1 visible, is there a call to action, do pop-ups cover it, are tap targets big enough, is the text readable, does it scroll sideways (and which element causes it), how much does the layout shift, and which element is the largest. Also checks design and readability: text with too little contrast (WCAG AA), inconsistent button styles and uneven spacing between sections. Also loads it with JavaScript off and shows what crawlers without JavaScript (GPTBot, ClaudeBot) miss, and whether the first screen delivers what the Google snippet promises. Returns screenshots. OnPage.dev has a small daily budget of browser time; if it is used up, or if you have your own browser tool, use get_layout_probe and analyze_layout instead.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address of the page, for example https://example.com/pricing."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "devices": {
      "type": "array",
      "items": {
        "type": "object"
      }
    },
    "issues": {
      "type": "array",
      "items": {
        "type": "object"
      }
    }
  },
  "required": [
    "devices",
    "issues"
  ]
}
🟢get_layout_probe

Get a small JavaScript measurement script to run in your own browser tool (Claude in Chrome, Playwright, Puppeteer or similar). Run it on the page at each viewport listed, after the page has loaded, then pass the results to analyze_layout. Use this when you have a browser: it has no daily limit, and it works on pages behind a login or on localhost.

Esquema de entrada

{
  "type": "object",
  "properties": {},
  "required": [],
  "additionalProperties": false
}
🟢analyze_layout(url, results, no_js)

Analyse the results of the get_layout_probe script, measured in your own browser: the same checks as render_page (H1 and call to action position, pop-ups, tap targets, small text, sideways scrolling and its cause, low-contrast text, inconsistent buttons, uneven spacing, layout shift, largest element), plus a comparison with the HTML the server sends. For a page that is not public (localhost, staging behind a login), the comparison with the server HTML is skipped.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address of the page, for example https://example.com/pricing."
    },
    "results": {
      "type": "array",
      "minItems": 1,
      "maxItems": 4,
      "items": {
        "type": "object"
      },
      "description": "One probe result per viewport, each with device set to phone, tablet or desktop."
    },
    "no_js": {
      "type": "object",
      "description": "Optional: the probe result with JavaScript turned off, for an exact comparison."
    }
  },
  "required": [
    "url",
    "results"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "devices": {
      "type": "array",
      "items": {
        "type": "object"
      }
    },
    "issues": {
      "type": "array",
      "items": {
        "type": "object"
      }
    }
  },
  "required": [
    "devices",
    "issues"
  ]
}
🟢screen_reader_view(url, tree)

Show a page the way a screen reader announces it, from the browser's accessibility tree: landmarks, the heading outline, and the reading order of links, buttons, images and form fields with the names they get. Flags what makes the page hard to use and hard to understand for assistive tech and for AI agents that browse through the accessibility tree: links and buttons without a name, vague link text like 'read more', form fields without a label, missing main landmark, skipped heading levels, and visible text hidden from readers. Uses the same browser render as render_page (shared, so calling both costs one render). If you have your own browser tool, pass its accessibility snapshot as tree instead.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address of the page."
    },
    "tree": {
      "type": "object",
      "description": "Optional: an accessibility snapshot from your own browser (role, name, level, children), for example Puppeteer page.accessibility.snapshot()."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "landmarks": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "headings": {
      "type": "array",
      "items": {
        "type": "object"
      }
    },
    "issues": {
      "type": "array",
      "items": {
        "type": "object"
      }
    }
  },
  "required": [
    "issues"
  ]
}
🟡export_findings(url, audit_id, slack_webhook_url)

Turn a page scan or a finished site audit into an action plan the team can work from. Returns: rows for a spreadsheet plus a private CSV link that loads straight into Google Sheets with =IMPORTDATA (no connector needed), a ready Slack message, one task per issue for Linear, Jira, Asana, Trello or GitHub Issues, and a Markdown checklist for Notion or Confluence. If the user has a Google Sheets, Slack, Notion or task board tool connected, use it to send the output there. Optionally posts the Slack message to an https incoming webhook. Pass url for one page or audit_id for a whole site.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Page to export the findings of."
    },
    "audit_id": {
      "type": "string",
      "description": "A finished site audit from start_site_audit, to export the whole site."
    },
    "slack_webhook_url": {
      "type": "string",
      "description": "Optional https incoming webhook (Slack, Discord, Teams) to post the summary to."
    }
  },
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "csv": {
      "type": "string"
    },
    "sheetsFormula": {
      "type": "string"
    },
    "rows": {
      "type": "array",
      "items": {
        "type": "object"
      }
    },
    "slack": {
      "type": "string"
    },
    "tasks": {
      "type": "array",
      "items": {
        "type": "object"
      }
    }
  },
  "required": [
    "rows",
    "csv"
  ]
}
🟢measure_impact(pages, fix_date, days, source, watch_ids)

Show whether SEO fixes paid off, using numbers from the user's connected tools. Fetch two periods of equal length from Google Search Console, GA4, Ahrefs or Semrush, one before and one after the fix date (28 days each works well), for the pages you changed and, ideally, a few pages you did not change as a control group. Pass them here with changed true or false. OnPage.dev compares clicks, impressions, CTR and position, subtracts the trend of the unchanged pages so seasonality and Google updates are not counted as your result, and lists what changed on each page from the watch history when you pass a watch_id. The numbers are used for this answer only and not stored.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "pages": {
      "type": "array",
      "minItems": 1,
      "maxItems": 50,
      "items": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "changed": {
            "type": "boolean",
            "description": "true for pages you fixed, false for the control group."
          },
          "fix": {
            "type": "string",
            "description": "Optional: what was fixed on this page."
          },
          "before": {
            "type": "object",
            "properties": {
              "clicks": {
                "type": "number",
                "minimum": 0
              },
              "impressions": {
                "type": "number",
                "minimum": 0
              },
              "ctr": {
                "type": "number",
                "minimum": 0
              },
              "position": {
                "type": "number",
                "minimum": 0
              },
              "traffic": {
                "type": "number",
                "minimum": 0
              }
            },
            "additionalProperties": false
          },
          "after": {
            "type": "object",
            "properties": {
              "clicks": {
                "type": "number",
                "minimum": 0
              },
              "impressions": {
                "type": "number",
                "minimum": 0
              },
              "ctr": {
                "type": "number",
                "minimum": 0
              },
              "position": {
                "type": "number",
                "minimum": 0
              },
              "traffic": {
                "type": "number",
                "minimum": 0
              }
            },
            "additionalProperties": false
          }
        },
        "required": [
          "url",
          "before",
          "after"
        ]
      }
    },
    "fix_date": {
      "type": "string",
      "description": "Date the fixes went live, YYYY-MM-DD."
    },
    "days": {
      "type": "integer",
      "minimum": 7,
      "maximum": 365,
      "description": "Length of each period in days."
    },
    "source": {
      "type": "string",
      "enum": [
        "gsc",
        "ga4",
        "ahrefs",
        "semrush",
        "other"
      ]
    },
    "watch_ids": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 20,
      "description": "Optional watch ids, to list what changed on each page and when."
    }
  },
  "required": [
    "pages"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "changed": {
      "type": "object"
    },
    "control": {
      "type": [
        "object",
        "null"
      ]
    },
    "pages": {
      "type": "array",
      "items": {
        "type": "object"
      }
    }
  },
  "required": [
    "changed",
    "pages"
  ]
}
🟢match_intent(url, keyword, competitors, queries)

Check whether a page matches what searchers want for a keyword, based on what actually ranks. Fetch the top organic results for the keyword with the user's connected Ahrefs, Semrush or other SERP tool (5 to 8 URLs), and pass them as competitors with your page as url. OnPage.dev scans every page, one per call (call again with the same arguments until done), works out the page type Google rewards (guide, product page, category page, comparison or list, tool, local page, homepage) and the format (length, headings, FAQ, year in the title), and tells you whether your page fits and what to change. Without competitors it classifies the keyword wording and your page only. Or pass queries: Search Console rows (query, page, clicks, impressions, position) to find pages that compete for the same query and pages that attract mixed intents.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Your page."
    },
    "keyword": {
      "type": "string",
      "description": "The search term."
    },
    "competitors": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 8,
      "description": "Top organic results for the keyword, in ranking order."
    },
    "queries": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          },
          "page": {
            "type": "string"
          },
          "clicks": {
            "type": "number"
          },
          "impressions": {
            "type": "number"
          },
          "position": {
            "type": "number"
          }
        },
        "required": [
          "query",
          "page"
        ]
      },
      "maxItems": 1000,
      "description": "Search Console rows by query and page, for the site-wide check."
    }
  },
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "keywordIntent": {
      "type": [
        "string",
        "null"
      ]
    },
    "serp": {
      "type": [
        "object",
        "null"
      ]
    },
    "yours": {
      "type": [
        "object",
        "null"
      ]
    },
    "cannibalisation": {
      "type": "array",
      "items": {
        "type": "object"
      }
    },
    "mixedPages": {
      "type": "array",
      "items": {
        "type": "object"
      }
    }
  }
}
🟢check_readability(url, keyword, competitors)

Check how easy a page is to read, against the right target. A product page should read differently from documentation, so the target depends on the page type (guide, listicle, product, category, service, docs, news, recipe and more). For the best benchmark, also pass the keyword and the top results from the user's Ahrefs or Semrush as competitors: OnPage.dev scans them (one per call, call again until done) and compares your reading ease with the pages that rank. Returns the Flesch reading ease (Flesch-Douma for Dutch), average sentence length, the share of long sentences, and the hardest sentences and paragraphs to rewrite first.

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Your page."
    },
    "keyword": {
      "type": "string",
      "description": "Optional: the search term, for context."
    },
    "competitors": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 8,
      "description": "Optional: top organic results for the keyword."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "score": {
      "type": [
        "number",
        "null"
      ]
    },
    "target": {
      "type": [
        "object",
        "null"
      ]
    },
    "hardestSentences": {
      "type": "array",
      "items": {
        "type": "object"
      }
    }
  },
  "required": [
    "score"
  ]
}
🟢check_og_tags(url)

Check how a page looks when it is shared on Facebook, LinkedIn, X, WhatsApp, Slack or iMessage: every Open Graph and Twitter Card tag, and the share image itself (does it load, its real size in pixels, file type and weight) against what these platforms need. Returns a score, the issues to fix and the tags to add. The same check is free as a public REST API: GET https://onpage.dev/api/v1/og?url=…

Esquema de entrada

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "Full address of the page."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false
}

Esquema de salida

{
  "type": "object",
  "properties": {
    "score": {
      "type": "number"
    },
    "tags": {
      "type": "object"
    },
    "image": {
      "type": [
        "object",
        "null"
      ]
    },
    "issues": {
      "type": "array",
      "items": {
        "type": "object"
      }
    }
  },
  "required": [
    "score",
    "issues"
  ]
}

Comunidad

Califica este servidor

Evidencia

Observaciones recientes

verificadoversión no registrada39 herramientas