Speculation Rules
Páginas que se abren al instante porque el navegador las prepara antes del clic.
Un bloque <script type="speculationrules"> (o la cabecera Speculation-Rules) indica qué enlaces precargar (prefetch) o renderizar por completo en segundo plano (prerender), y con cuánta antelación: immediate, eager, moderate (en escritorio, 200 ms sobre el enlace o al pulsar; en móvil, según lo que hay en pantalla) o conservative (al pulsar).
Solo en Chromium: Chrome y Edge desde la 109 (las reglas por documento y la antelación, desde la 121). Safari 26.2 tiene prefetch tras una flag y Firefox no la implementa. Es una mejora progresiva: donde no existe, los enlaces cargan como siempre.
Para qué sirve
- Que el siguiente paso de un proceso de compra esté listo
- Navegación instantánea en webs de contenido
- Prerenderizar el resultado más probable de una búsqueda
Demo
Esta página pide prerenderizar el destino A en cuanto se carga. El B se carga de forma normal. Abre los dos y compara: la página de destino te dice si estaba prerenderizada.
<script type="speculationrules">
{
"prerender": [
{
"urls": [
"/speculation-rules/destino-a/"
],
"eagerness": "immediate"
}
]
}
</script>Compatibilidad
Disponibilidad limitada| Función | Escritorio | Móvil | |||||
|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Safari | Chrome Android | Firefox Android | Safari iOS | |
| <script type="speculationrules"> | 109Chrome: 109 | 109Edge: 109 | —Firefox: No | 26.2flagSafari: 26.2 flag | 109Chrome: 109 | —Firefox: No | 26.2flagSafari: 26.2 flag |
| prerender | 105Chrome: 105 | 105Edge: 105 | —Firefox: No | —Safari: No | 103Chrome: 103 | —Firefox: No | —Safari: No |
| prefetch | 110Chrome: 110 | 110Edge: 110 | —Firefox: No | 26.2flagSafari: 26.2 flag | 103Chrome: 103 | —Firefox: No | 26.2flagSafari: 26.2 flag |
Compatibilidad generada en cada publicación desde MDN browser-compat-data 8.1.3 (24 sep 2026) · web-features 3.40.0 · revisión manual: 1 oct 2026
Código mínimo
<!doctype html>
<meta charset="utf-8">
<title>Speculation Rules · ejemplo mínimo</title>
<!-- Prerenderiza los enlaces de esta web al pasar el ratón (200 ms) o al empezar a pulsar.
Chromium 109+. Sírvelo por HTTP (npx serve .). -->
<script type="speculationrules">
{
"prerender": [{
"source": "document",
"where": { "and": [
{ "href_matches": "/*" },
{ "not": { "selector_matches": "[data-no-prerender]" } }
] },
"eagerness": "moderate"
}]
}
</script>
<p>Soporte: <b id="support"></b></p>
<p><a href="destino.html">Ir al destino (se prerenderiza)</a></p>
<p><a href="destino.html?x" data-no-prerender>Ir al destino sin prerenderizar</a></p>
<script>
document.querySelector('#support').textContent =
HTMLScriptElement.supports?.('speculationrules') ? 'sí' : 'no (los enlaces cargan de forma normal)';
</script><!doctype html>
<meta charset="utf-8">
<title>Speculation Rules · ejemplo mínimo</title>
<!-- Prerenderiza los enlaces de esta web al pasar el ratón (200 ms) o al empezar a pulsar.
Chromium 109+. Sírvelo por HTTP (npx serve .). -->
<script type="speculationrules">
{
"prerender": [{
"source": "document",
"where": { "and": [
{ "href_matches": "/*" },
{ "not": { "selector_matches": "[data-no-prerender]" } }
] },
"eagerness": "moderate"
}]
}
</script>
<p>Soporte: <b id="support"></b></p>
<p><a href="destino.html">Ir al destino (se prerenderiza)</a></p>
<p><a href="destino.html?x" data-no-prerender>Ir al destino sin prerenderizar</a></p>
<script>
document.querySelector('#support').textContent =
HTMLScriptElement.supports?.('speculationrules') ? 'sí' : 'no (los enlaces cargan de forma normal)';
</script><!doctype html>
<meta charset="utf-8">
<title>Speculation Rules · destino</title>
<p id="out">…</p>
<p><a href="index.html">Volver</a></p>
<script>
const out = document.querySelector('#out');
const show = () => {
// activationStart > 0: la página ya estaba prerenderizada cuando la persona llegó
const nav = performance.getEntriesByType('navigation')[0];
out.textContent = nav?.activationStart > 0
? `Prerenderizada: se mostró ${Math.round(performance.now() - nav.activationStart)} ms después de activarse.`
: 'Carga normal (sin prerenderizar).';
};
// Mientras se prerenderiza, no cuentes visitas ni lances analítica
if (document.prerendering) document.addEventListener('prerenderingchange', show, { once: true });
else show();
</script><!doctype html>
<meta charset="utf-8">
<title>Speculation Rules · destino</title>
<p id="out">…</p>
<p><a href="index.html">Volver</a></p>
<script>
const out = document.querySelector('#out');
const show = () => {
// activationStart > 0: la página ya estaba prerenderizada cuando la persona llegó
const nav = performance.getEntriesByType('navigation')[0];
out.textContent = nav?.activationStart > 0
? `Prerenderizada: se mostró ${Math.round(performance.now() - nav.activationStart)} ms después de activarse.`
: 'Carga normal (sin prerenderizar).';
};
// Mientras se prerenderiza, no cuentes visitas ni lances analítica
if (document.prerendering) document.addEventListener('prerenderingchange', show, { once: true });
else show();
</script>Novedades
Ten en cuenta
- Nunca especules con URLs que cambian algo (cerrar sesión, carrito).
- No cuentes visitas mientras document.prerendering sea true; espera a prerenderingchange.
- Las reglas en línea necesitan 'inline-speculation-rules' en la CSP; por cabecera, el JSON se sirve como application/speculationrules+json.
Más información
Fuentes
- Chrome · Prerender pages23 ene 2026
- MDN · Speculation Rules API10 sep 2026
- Chrome 151 release notes28 jul 2026
- MDN browser-compat-data 8.1.324 sep 2026