<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Erick Eduardo Ramos</title>
    <description>The latest articles on DEV Community by Erick Eduardo Ramos (@erickeduardoramos03).</description>
    <link>https://dev.to/erickeduardoramos03</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3943545%2Ff8b96fcc-b7e6-4c21-a809-3c6ffedaea58.png</url>
      <title>DEV Community: Erick Eduardo Ramos</title>
      <link>https://dev.to/erickeduardoramos03</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/erickeduardoramos03"/>
    <language>en</language>
    <item>
      <title>Cómo solucionar el error “Text content does not match server-rendered HTML” en Next.js App Router</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Wed, 12 Aug 2026 09:55:24 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-error-text-content-does-not-match-server-rendered-html-en-nextjs-app-router-10ag</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-error-text-content-does-not-match-server-rendered-html-en-nextjs-app-router-10ag</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el error “Text content does not match server-rendered HTML” en Next.js App Router
&lt;/h1&gt;

&lt;p&gt;Este error ocurre cuando el HTML generado en el servidor (SSR/SSG) no coincide con el árbol de React que se genera durante la primera renderización en el cliente (hydration). React detecta una inconsistencia crítica y detiene la hidratación para evitar comportamientos impredecibles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Causa raíz
&lt;/h2&gt;

&lt;p&gt;En tu caso, el problema &lt;strong&gt;no es un error de lógica de renderizado obvio&lt;/strong&gt; (como &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; anidado en otro &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt;), sino una &lt;strong&gt;diferencia temporal o contextual&lt;/strong&gt; entre el servidor y el cliente. Las causas más probables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uso de &lt;code&gt;Date.now()&lt;/code&gt;, &lt;code&gt;new Date()&lt;/code&gt;, o &lt;code&gt;Math.random()&lt;/code&gt; en el renderizado.&lt;/li&gt;
&lt;li&gt;Acceso directo a &lt;code&gt;window&lt;/code&gt;, &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;navigator&lt;/code&gt;, etc. durante la renderización.&lt;/li&gt;
&lt;li&gt;Uso de &lt;code&gt;typeof window !== 'undefined'&lt;/code&gt; &lt;strong&gt;dentro del cuerpo del componente&lt;/strong&gt; (no dentro de &lt;code&gt;useEffect&lt;/code&gt; o &lt;code&gt;useMemo&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Metaetiqueta &lt;code&gt;format-detection&lt;/code&gt; de iOS activa → convierte números de teléfono en &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; → rompe el DOM.&lt;/li&gt;
&lt;li&gt;Extensiones del navegador (ej. traductores, dark mode) modificando el DOM antes de la hidratación.&lt;/li&gt;
&lt;li&gt;Configuración de CDN (Cloudflare Auto Minify, etc.) que altera el HTML prerenderizado.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Solución definitiva (pasos verificados)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Paso 1: Busca y elimina dependencias de tiempo o contexto del renderizado
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;❌ Mal:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ ¡Esto rompe la hidratación!&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ❌ El servidor y el cliente tienen hora distinta&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Última actualización: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Bien (opción 1: renderiza placeholder en SSR, luego actualiza):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setNow&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cargando...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setNow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Última actualización: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Bien (opción 2: usa &lt;code&gt;suppressHydrationWarning&lt;/code&gt; solo si es inevitable):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Última actualización: 
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt; 
        &lt;span class="na"&gt;suppressHydrationWarning&lt;/span&gt; 
        &lt;span class="na"&gt;dateTime&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Pro-tip:&lt;/strong&gt; &lt;code&gt;suppressHydrationWarning&lt;/code&gt; &lt;strong&gt;solo debe usarse en elementos específicos&lt;/strong&gt;, nunca en el &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; o &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;. React ignora &lt;em&gt;solo ese nodo&lt;/em&gt; durante la comparación.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  ✅ Paso 2: Deshabilita detección automática de iOS (¡frecuente causa silenciosa!)
&lt;/h3&gt;

&lt;p&gt;Agrega esta metaetiqueta en &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; de &lt;code&gt;app/layout.tsx&lt;/code&gt; (o &lt;code&gt;app/layout.tsx&lt;/code&gt; si usas App Router):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/layout.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"es"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* 👇 SOLUCIÓN CLAVE PARA iOS */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"format-detection"&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"telephone=no, date=no, email=no, address=no"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🔍 &lt;strong&gt;¿Por qué?&lt;/strong&gt; iOS convierte automáticamente números como &lt;code&gt;1-800-555-0199&lt;/code&gt; en &lt;code&gt;&amp;lt;a href="tel:..."&amp;gt;&lt;/code&gt;. Esto modifica el DOM prerenderizado → mismatch.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  ✅ Paso 3: Evita APIs del navegador en render
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;❌ Mal:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isMobile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ❌&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isMobile&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Móvil&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Escritorio&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Bien (con &lt;code&gt;useEffect&lt;/code&gt; + estado):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isMobile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsMobile&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkMobile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setIsMobile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;checkMobile&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;checkMobile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;checkMobile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isMobile&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Móvil&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Escritorio&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Alternativa (recomendada en App Router): usa &lt;code&gt;headers().get('User-Agent')&lt;/code&gt; en el servidor:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/page.tsx (Server Component)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/headers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headersList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ua&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;headersList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user-agent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isMobile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/Mobi|Android/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ua&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isMobile&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Móvil&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Escritorio&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ✅ Paso 4: Verifica configuración de CDN
&lt;/h3&gt;

&lt;p&gt;Si usas &lt;strong&gt;Cloudflare&lt;/strong&gt;, &lt;strong&gt;Vercel Edge Config&lt;/strong&gt;, o cualquier proxy intermedio:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare:&lt;/strong&gt; Desactiva &lt;em&gt;Auto Minify&lt;/em&gt; (HTML) y &lt;em&gt;Rocket Loader&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel:&lt;/strong&gt; Asegúrate de no tener &lt;code&gt;vercel dev&lt;/code&gt; con &lt;code&gt;--turbo&lt;/code&gt; (puede alterar SSR).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Otros:&lt;/strong&gt; Busca reglas que modifiquen &lt;code&gt;Content-Type: text/html&lt;/code&gt; (ej. reglas de reescritura, optimización de imágenes en HTML, etc.).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Bloque de código corregido (ejemplo completo)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/page.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/headers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ✅ Seguro: se evalúa en el servidor&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ua&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user-agent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isMobile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/Mobi|Android/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ua&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Estado: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isMobile&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Móvil&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Escritorio&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Última actualización: 
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt; 
          &lt;span class="na"&gt;suppressHydrationWarning&lt;/span&gt; 
          &lt;span class="na"&gt;dateTime&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/layout.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"es"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ✅ Previene iOS from modifying DOM */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"format-detection"&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"telephone=no, date=no, email=no, address=no"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Pro-tip: Diagnóstico rápido
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reproduce en modo incógnito&lt;/strong&gt; (sin extensiones).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Desactiva Cloudflare/Vercel Edge&lt;/strong&gt; temporalmente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Busca en el código:&lt;/strong&gt; &lt;code&gt;new Date()&lt;/code&gt;, &lt;code&gt;window.&lt;/code&gt;, &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;Math.random()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa &lt;code&gt;console.log('CLIENT')&lt;/code&gt; dentro de &lt;code&gt;useEffect&lt;/code&gt;&lt;/strong&gt; para confirmar qué se renderiza en cliente vs servidor.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;🚨 &lt;strong&gt;Nunca uses &lt;code&gt;suppressHydrationWarning&lt;/code&gt; como solución principal.&lt;/strong&gt; Es un escape hatch, no un parche. Si el 90% de tu app usa &lt;code&gt;suppressHydrationWarning&lt;/code&gt;, hay un problema arquitectónico.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;¡Listo! Con esto el error desaparecerá de forma definitiva.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>nextjs</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Cómo solucionar el error “Enable JavaScript and cookies to continue”</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Tue, 11 Aug 2026 09:54:14 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-error-enable-javascript-and-cookies-to-continue-1de9</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-error-enable-javascript-and-cookies-to-continue-1de9</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el error “Enable JavaScript and cookies to continue”
&lt;/h1&gt;

&lt;p&gt;Este mensaje aparece cuando &lt;strong&gt;Cloudflare&lt;/strong&gt; (u otro proxy de seguridad similar) bloquea la solicitud porque detecta que el cliente no cumple con los requisitos mínimos de seguridad: JavaScript está deshabilitado o las cookies no están permitidas.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Por qué ocurre?
&lt;/h2&gt;

&lt;p&gt;Cloudflare implementa mecanismos de protección contra bots y ataques automatizados. Cuando una solicitud llega sin:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ejecutar JavaScript (necesario para resolver el &lt;em&gt;JavaScript Challenge&lt;/em&gt;),&lt;/li&gt;
&lt;li&gt;o sin aceptar cookies (para mantener el estado de la sesión tras la validación),&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...Cloudflare interrumpe la conexión y muestra este mensaje.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Causas comunes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uso de &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;wget&lt;/code&gt;, o scripts sin motor JS (como Node.js puro sin Puppeteer/Playwright).&lt;/li&gt;
&lt;li&gt;Configuración de navegador que bloquea JavaScript o cookies.&lt;/li&gt;
&lt;li&gt;Requests desde herramientas de scraping o automatización sin emular un navegador real.&lt;/li&gt;
&lt;li&gt;Errores en el flujo de validación de Cloudflare (raro, pero posible si hay redirecciones rotas).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Pasos para solucionarlo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ 1. Si eres un usuario final (navegando):
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Habilita JavaScript&lt;/strong&gt; en tu navegador:

&lt;ul&gt;
&lt;li&gt;Chrome: &lt;code&gt;Configuración &amp;gt; Privacidad y seguridad &amp;gt; Seguridad &amp;gt; Permitir JavaScript&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Firefox: &lt;code&gt;Preferencias &amp;gt; Privacidad y seguridad &amp;gt; Permisos &amp;gt; Habilitar JavaScript&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Habilita cookies de terceros&lt;/strong&gt; (si el sitio usa dominios distintos para autenticación):

&lt;ul&gt;
&lt;li&gt;Chrome: &lt;code&gt;Configuración &amp;gt; Privacidad y seguridad &amp;gt; Cookies y otros datos de sitios &amp;gt; Permitir cookies de terceros&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Borra la caché y las cookies del dominio problemático.&lt;/li&gt;
&lt;li&gt;Prueba en modo incógnito (para descartar extensiones bloqueantes).&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  ✅ 2. Si eres desarrollador (haciendo requests programáticos)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  🔧 Opción A: Usa un navegador headless (recomendado)
&lt;/h4&gt;

&lt;p&gt;No intentes resolver el desafío manualmente. Usa herramientas que ejecuten JS y gestionen cookies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ejemplo con Puppeteer (Node.js)&lt;/span&gt;
npx puppeteer-core &lt;span class="nt"&gt;--executable-path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/path/to/chrome"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--no-sandbox&lt;/span&gt; &lt;span class="nt"&gt;--disable-setuid-sandbox&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--disable-dev-shm-usage&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--viewport-width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1920 &lt;span class="nt"&gt;--viewport-height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1080 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--user-agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30000 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--wait-for-selector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"body"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O en código (Node.js con &lt;code&gt;puppeteer&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;puppeteer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;puppeteer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puppeteer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;headless&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;new&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--no-sandbox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--disable-setuid-sandbox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Simula un navegador real&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setUserAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;waitUntil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;networkidle2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Espera a que se resuelva el desafío (Cloudflare lo hace automáticamente)&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body:not(:has(#challenge-error-text))&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30000&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  🔧 Opción B: Usa &lt;code&gt;cloudscraper&lt;/code&gt; (solo para sitios con Cloudflare &lt;em&gt;básico&lt;/em&gt;)
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Solo funciona si Cloudflare no usa &lt;em&gt;Managed Challenge&lt;/em&gt; o &lt;em&gt;Under Attack Mode&lt;/em&gt;. Ya está obsoleto, pero hay forks activos.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;cloudscraper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cloudscraper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cloudscraper&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;cloudscraper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Importante: gestiona cookies&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User-Agent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fallo:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  🔧 Opción C: Usa &lt;code&gt;playwright&lt;/code&gt; (más robusto que Puppeteer hoy en día)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;playwright
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;chromium&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;playwright&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;headless&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForLoadState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;networkidle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Espera a que todo cargue, incluido JS&lt;/span&gt;

  &lt;span class="c1"&gt;// Si Cloudflare pide interacción manual (raro en headless), usa:&lt;/span&gt;
  &lt;span class="c1"&gt;// await page.click('#challenge-form button'); // si hay botón explícito&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Pro-tip: Verifica si Cloudflare está activo y qué modo usa
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Abre &lt;code&gt;https://www.cloudflare.com/ssl-website/&lt;/code&gt; y entra tu dominio.&lt;/li&gt;
&lt;li&gt;O usa &lt;code&gt;dig&lt;/code&gt; para ver los registros DNS y confirmar si está detrás de Cloudflare:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   dig example.com +short
   &lt;span class="c"&gt;# Si ves IPs como 104.16.x.x o 172.67.x.x → está en Cloudflare.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Revisa en el panel de Cloudflare:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security &amp;gt; Settings &amp;gt; Browser Integrity Check&lt;/strong&gt; → debe estar &lt;em&gt;On&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security &amp;gt; Bot Fight Mode&lt;/strong&gt; o &lt;strong&gt;Under Attack Mode&lt;/strong&gt; → si están activos, el desafío será más estricto.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Clave&lt;/strong&gt;: Si estás haciendo scraping, &lt;strong&gt;no evites el desafío&lt;/strong&gt;. Usa una estrategia de resolución real (con JS). Cloudflare detecta requests sin JS y los bloquea intencionalmente.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;✅ &lt;strong&gt;Solución definitiva&lt;/strong&gt;: Usa un navegador headless real (Puppeteer/Playwright) con cookies habilitadas y espera a que se resuelva el desafío. No hay atajos seguros ni sostenibles.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>security</category>
      <category>tutorial</category>
      <category>webscraping</category>
    </item>
    <item>
      <title>Cómo solucionar el error \"Text content does not match server-rendered HTML\" en Next.js App Router</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Mon, 10 Aug 2026 10:11:12 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-error-text-content-does-not-match-server-rendered-html-en-nextjs-app-router-3905</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-error-text-content-does-not-match-server-rendered-html-en-nextjs-app-router-3905</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el error "Text content does not match server-rendered HTML" en Next.js App Router
&lt;/h1&gt;

&lt;p&gt;Este error ocurre cuando el HTML generado en el servidor (SSR/SSG) no coincide con el árbol de React generado durante la primera renderización en el cliente. React detecta la inconsistencia durante el proceso de &lt;em&gt;hydration&lt;/em&gt; y lanza una advertencia crítica que puede romper la funcionalidad de tu app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Causa raíz
&lt;/h2&gt;

&lt;p&gt;La mayoría de los casos provienen de &lt;strong&gt;código no idempotente entre SSR y CSR&lt;/strong&gt;, es decir, código que produce resultados diferentes dependiendo de si se ejecuta en el servidor o en el navegador. Las causas más frecuentes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uso de &lt;code&gt;Date.now()&lt;/code&gt;, &lt;code&gt;new Date()&lt;/code&gt;, &lt;code&gt;Math.random()&lt;/code&gt; o APIs dependientes del tiempo en el renderizado.&lt;/li&gt;
&lt;li&gt;Acceso directo a &lt;code&gt;window&lt;/code&gt;, &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;navigator&lt;/code&gt;, etc. sin protección.&lt;/li&gt;
&lt;li&gt;Lógica condicional basada en &lt;code&gt;typeof window !== 'undefined'&lt;/code&gt; dentro del JSX.&lt;/li&gt;
&lt;li&gt;Extensiones del navegador que inyectan elementos (ej. ad-blockers, traductores).&lt;/li&gt;
&lt;li&gt;Metaetiqueta &lt;code&gt;format-detection&lt;/code&gt; de iOS que modifica el DOM tras la carga inicial.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Solución definitiva (pasos verificados)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Paso 1: Identifica el elemento problemático
&lt;/h3&gt;

&lt;p&gt;Busca en el stack trace del error el componente y la línea exacta. Si no está claro:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Abre DevTools → pestaña &lt;em&gt;Console&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Haz clic en el error → verás el mensaje detallado con la ruta del componente.&lt;/li&gt;
&lt;li&gt;Busca en ese componente:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Date&lt;/code&gt;, &lt;code&gt;Math.random()&lt;/code&gt;, &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;window.innerWidth&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;Uso de &lt;code&gt;useEffect&lt;/code&gt; que modifique el estado &lt;em&gt;antes&lt;/em&gt; de la primera renderización.&lt;/li&gt;
&lt;li&gt;Uso de &lt;code&gt;typeof window !== 'undefined'&lt;/code&gt; en el cuerpo del componente (no dentro de &lt;code&gt;useEffect&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  ✅ Paso 2: Aplica la solución según el caso
&lt;/h3&gt;

&lt;h4&gt;
  
  
  🔹 Caso A: Contenido dinámico (ej. fecha/hora, ID aleatorio)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Incorrecto:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Timestamp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Diferente en SSR vs CSR&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Correcto (opción 1): Usa &lt;code&gt;suppressHydrationWarning&lt;/code&gt; para contenido inmutable&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Timestamp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt; &lt;span class="na"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;suppressHydrationWarning&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Correcto (opción 2): Usa &lt;code&gt;useEffect&lt;/code&gt; para retrasar la renderización&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Timestamp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTimestamp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTimestamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  🔹 Caso B: Acceso a APIs del navegador (&lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;window&lt;/code&gt;, etc.)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Incorrecto:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ThemeToggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Error en SSR&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;🌙&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;☀️&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Correcto: Usa &lt;code&gt;useEffect&lt;/code&gt; + estado local&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ThemeToggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isDark&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsDark&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stored&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setIsDark&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stored&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;🌙&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;☀️&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  🔹 Caso C: Lógica condicional basada en entorno
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;❌ Incorrecto:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ResponsiveLayout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isMobile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isMobile&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mobile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Desktop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Correcto: Usa &lt;code&gt;useEffect&lt;/code&gt; para detectar tamaño de pantalla&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ResponsiveLayout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isMobile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsMobile&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkMobile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setIsMobile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;checkMobile&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;checkMobile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;checkMobile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isMobile&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mobile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Desktop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  🔹 Caso D: iOS inyecta enlaces automáticamente
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;✅ Solución definitiva: Agrega la metaetiqueta en &lt;code&gt;app/layout.tsx&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/layout.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"es"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"format-detection"&lt;/span&gt;
          &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"telephone=no, date=no, email=no, address=no"&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛠️ Bloque de código corregido (ejemplo completo)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/page.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsClient&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCurrentTime&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIsClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setCurrentTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleTimeString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;App Router Features&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Latest Version: 16.3.0&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Contenido seguro para SSR/CSR */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt; 
        &lt;span class="na"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
        &lt;span class="na"&gt;suppressHydrationWarning&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;currentTime&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cargando...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Componente con lógica client-only */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isClient&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ClientOnlyComponent&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Componente client-only explícito&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ClientOnlyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./ClientOnly&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;ssr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💡 Pro-tip: Prevención a largo plazo
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Herramientas de detección temprana:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="c"&gt;# Instala ESLint plugin para Next.js&lt;/span&gt;
   npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; eslint-plugin-next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configura en &lt;code&gt;.eslintrc.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"next/core-web-vitals"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plugin:next/recommended"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto detecta usos inseguros de &lt;code&gt;window&lt;/code&gt;, &lt;code&gt;localStorage&lt;/code&gt;, etc.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Regla de oro para SSR:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Todo lo que se renderice en el JSX debe producir el mismo resultado en el servidor y en el cliente.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Para componentes 100% client-side:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;   &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dynamic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/dynamic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ClientComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./ClientComponent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ssr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Verifica en producción:&lt;/strong&gt;
Usa &lt;code&gt;next build &amp;amp;&amp;amp; next start&lt;/code&gt; para reproducir el entorno de producción (donde ocurren más errores de hydration).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;✅ &lt;strong&gt;Resultado:&lt;/strong&gt; El error desaparece, la app se hydrata correctamente y el usuario ve contenido consistente desde la primera interacción.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>nextjs</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Cómo solucionar `docker run` con exit code 1 en Raspberry Pi</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Sun, 09 Aug 2026 09:32:11 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-docker-run-con-exit-code-1-en-raspberry-pi-2kl7</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-docker-run-con-exit-code-1-en-raspberry-pi-2kl7</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar &lt;code&gt;docker run&lt;/code&gt; con exit code 1 en Raspberry Pi
&lt;/h1&gt;

&lt;h2&gt;
  
  
  ¿Por qué ocurre?
&lt;/h2&gt;

&lt;p&gt;El error &lt;code&gt;Exited (1)&lt;/code&gt; indica que el proceso principal del contenedor terminó con un código de error no cero. En tu caso específico, &lt;strong&gt;el problema está en el comando &lt;code&gt;docker run --net = host&lt;/code&gt;&lt;/strong&gt;. El signo igual (&lt;code&gt;=&lt;/code&gt;) entre &lt;code&gt;--net&lt;/code&gt; y &lt;code&gt;host&lt;/code&gt; &lt;strong&gt;no es válido en Docker CLI&lt;/strong&gt;. Docker interpreta &lt;code&gt;--net =&lt;/code&gt; como una opción desconocida, lo que provoca que el contenedor falle al iniciar.&lt;/p&gt;

&lt;p&gt;Esto explica por qué funciona en la VM (posiblemente con una versión más permisiva o con un shell que hace algo distinto con los espacios), pero &lt;strong&gt;falla en el Raspberry Pi físico&lt;/strong&gt; (donde el shell es más estricto y Docker rechaza la opción inválida).&lt;/p&gt;

&lt;h2&gt;
  
  
  Pasos para solucionarlo
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Elimina el signo igual y los espacios innecesarios&lt;/strong&gt; en la opción &lt;code&gt;--net&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Verifica que el contenedor se ejecute en primer plano para diagnosticar errores adicionales.&lt;/li&gt;
&lt;li&gt;Si persiste el problema, revisa los logs del contenedor.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Comando corregido
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ❌ INCORRECTO (con espacios y signo igual)&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage

&lt;span class="c"&gt;# ✅ CORRECTO (sin espacios ni signo igual)&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Nota crítica&lt;/strong&gt;: En versiones recientes de Docker, &lt;code&gt;--net=host&lt;/code&gt; &lt;strong&gt;no es compatible con Raspberry Pi en modo no privado&lt;/strong&gt; (es decir, si no estás ejecutando Docker como root o sin &lt;code&gt;sudo&lt;/code&gt;). Si sigues teniendo problemas, ejecuta con &lt;code&gt;sudo&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker run &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Diagnóstico adicional (si el error persiste)
&lt;/h2&gt;

&lt;p&gt;Si tras corregir el comando sigue fallando:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ejecuta en primer plano&lt;/strong&gt; para ver el error en tiempo real:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker run &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Elimina &lt;code&gt;-d&lt;/code&gt; y añade &lt;code&gt;-it&lt;/code&gt; para modo interactivo y terminal)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Revisa los logs del contenedor&lt;/strong&gt; si ya se creó:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker logs &amp;lt;nombre_o_id_del_contenedor&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Verifica compatibilidad de arquitectura&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Si la imagen &lt;code&gt;myimage&lt;/code&gt; fue construida para &lt;code&gt;amd64&lt;/code&gt; y ejecutas en Raspberry Pi (&lt;code&gt;armhf&lt;/code&gt; o &lt;code&gt;arm64&lt;/code&gt;), fallará silenciosamente.&lt;/li&gt;
&lt;li&gt;Usa &lt;code&gt;docker inspect myimage --format '{{.Architecture}}'&lt;/code&gt; para verificar.&lt;/li&gt;
&lt;li&gt;Si es necesario, reconstruye la imagen para ARM:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; docker build &lt;span class="nt"&gt;--platform&lt;/span&gt; linux/arm/v7 &lt;span class="nt"&gt;-t&lt;/span&gt; myimage &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Pro-tip: Automatiza la validación del comando
&lt;/h2&gt;

&lt;p&gt;Crea un script de verificación rápida:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# validate-docker-run.sh&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Validando sintaxis del comando..."&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$*&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ &lt;span class="s2"&gt;"--net&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="s2"&gt;*="&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"❌ ERROR: '--net' no debe tener espacios ni '='"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"   Usa: --net host (sin espacios ni signo igual)"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"✅ Sintaxis OK. Ejecutando..."&lt;/span&gt;
&lt;span class="nb"&gt;exec &lt;/span&gt;docker run &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Guarda como &lt;code&gt;validate-docker-run.sh&lt;/code&gt;, hazlo ejecutable (&lt;code&gt;chmod +x validate-docker-run.sh&lt;/code&gt;) y úsalo así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./validate-docker-run.sh &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🔍 &lt;strong&gt;Dato clave&lt;/strong&gt;: En Raspberry Pi, los errores de arquitectura y permisos son las segundas causas más comunes de &lt;code&gt;Exited (1)&lt;/code&gt; tras errores de sintaxis en el comando. Si todo falla, ejecuta &lt;code&gt;docker info&lt;/code&gt; y verifica que &lt;code&gt;Server Version&lt;/code&gt; y &lt;code&gt;Architecture&lt;/code&gt; coincidan con lo esperado para tu Raspberry Pi.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>debugging</category>
      <category>devops</category>
      <category>docker</category>
      <category>linux</category>
    </item>
    <item>
      <title>Cómo solucionar el error \"Enable JavaScript and cookies to continue\"</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Sat, 08 Aug 2026 09:30:56 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-error-enable-javascript-and-cookies-to-continue-4k9h</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-error-enable-javascript-and-cookies-to-continue-4k9h</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el error "Enable JavaScript and cookies to continue"
&lt;/h1&gt;

&lt;p&gt;Este mensaje no es un error de tu código, sino una &lt;strong&gt;protección activa de Cloudflare&lt;/strong&gt; (o similar, como Incapsula/Imperva) que bloquea la solicitud porque detecta que el cliente no cumple con los requisitos mínimos de seguridad: &lt;strong&gt;JavaScript habilitado y cookies aceptadas&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔍 Causa técnica
&lt;/h2&gt;

&lt;p&gt;Cloudflare implementa un desafío de "JavaScript Challenge" para distinguir entre navegadores reales y bots/scraper automatizados. Cuando una solicitud HTTP no incluye:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ejecución de JavaScript (para validar el desafío)&lt;/li&gt;
&lt;li&gt;Almacenamiento y reenvío de cookies (&lt;code&gt;cf_clearance&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...el servidor responde con esta página intermedia en lugar de servir el contenido real.&lt;/p&gt;

&lt;p&gt;Esto ocurre comúnmente en:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requests automatizados (Python &lt;code&gt;requests&lt;/code&gt;, &lt;code&gt;curl&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;Configuraciones de proxies sin soporte JS&lt;/li&gt;
&lt;li&gt;Navegadores headless mal configurados&lt;/li&gt;
&lt;li&gt;Pruebas con herramientas como Selenium sin manejo de cookies&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✅ Solución definitiva (3 enfoques)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🔧 Opción 1: Usa un navegador real (recomendado para scraping)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Con Selenium (Python)&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;selenium&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;selenium.webdriver.chrome.options&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Options&lt;/span&gt;

&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--disable-blink-features=AutomationControlled&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_experimental_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;excludeSwitches&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;enable-automation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_experimental_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;useAutomationExtension&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Chrome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://tu-sitio.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Espera a que Cloudflare resuelva el desafío (hasta 10s)
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Ahora sí tienes acceso al contenido real
&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_source&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Clave&lt;/strong&gt;: No uses &lt;code&gt;driver.get()&lt;/code&gt; y luego &lt;code&gt;time.sleep(0)&lt;/code&gt; — Cloudflare requiere tiempo para ejecutar su JS y establecer la cookie &lt;code&gt;cf_clearance&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🧪 Opción 2: Simula el desafío manualmente (avanzado)
&lt;/h3&gt;

&lt;p&gt;Si insistes en usar &lt;code&gt;requests&lt;/code&gt;, debes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hacer una petición inicial para obtener el HTML del desafío&lt;/li&gt;
&lt;li&gt;Extraer y ejecutar el script JS de validación (con &lt;code&gt;execjs&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Generar la cookie &lt;code&gt;cf_clearance&lt;/code&gt; válida&lt;/li&gt;
&lt;li&gt;Reintentar la petición con cookies y headers correctos&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Ejemplo simplificado con &lt;code&gt;cloudscraper&lt;/code&gt; (Python)&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;cloudscraper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cloudscraper&lt;/span&gt;

&lt;span class="n"&gt;scraper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cloudscraper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_scraper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;browser&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;firefox&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;platform&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;windows&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mobile&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scraper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://tu-sitio.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Ahora sí obtienes el contenido real
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ &lt;code&gt;cloudscraper&lt;/code&gt; maneja internamente el desafío JS y cookies.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🛠️ Opción 3: Configura Cloudflare (si eres el dueño del sitio)
&lt;/h3&gt;

&lt;p&gt;Si tú controlas el servidor:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Accede al panel de Cloudflare → &lt;strong&gt;Security → WAF&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Busca la regla &lt;strong&gt;"JavaScript Challenge"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Desactiva el desafío para tu IP o rango (solo para desarrollo)&lt;/li&gt;
&lt;li&gt;O usa &lt;strong&gt;"Under Attack Mode"&lt;/strong&gt; solo temporalmente&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;🚫 &lt;strong&gt;No recomendado en producción&lt;/strong&gt;: debilita la protección DDoS.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  💡 Pro-tip
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nunca confíes en &lt;code&gt;time.sleep()&lt;/code&gt; fijo&lt;/strong&gt; para esperar desafíos: usa &lt;code&gt;WebDriverWait&lt;/code&gt; con condiciones explícitas.&lt;/li&gt;
&lt;li&gt;Si usas headless, añade:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--disable-dev-shm-usage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--no-sandbox&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--disable-gpu&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Cloudflare cambia sus desafíos frecuentemente: &lt;code&gt;cloudscraper&lt;/code&gt; y Selenium son las soluciones más robustas a largo plazo.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;Verificación final&lt;/strong&gt;: Si la respuesta HTTP es &lt;code&gt;200 OK&lt;/code&gt; pero el contenido contiene &lt;code&gt;&amp;lt;span id="challenge-error-text"&amp;gt;&lt;/code&gt;, &lt;strong&gt;aún no has superado el desafío&lt;/strong&gt;. Revisa cookies y headers.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>javascript</category>
      <category>security</category>
      <category>webscraping</category>
    </item>
    <item>
      <title>Cómo solucionar `docker run` con exit code 1 en Raspberry Pi</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Fri, 07 Aug 2026 09:54:22 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-docker-run-con-exit-code-1-en-raspberry-pi-145e</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-docker-run-con-exit-code-1-en-raspberry-pi-145e</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar &lt;code&gt;docker run&lt;/code&gt; con exit code 1 en Raspberry Pi
&lt;/h1&gt;

&lt;h2&gt;
  
  
  ¿Por qué ocurre este error?
&lt;/h2&gt;

&lt;p&gt;El código de salida &lt;code&gt;1&lt;/code&gt; indica que el proceso principal del contenedor terminó con un error genérico. En Raspberry Pi, los casos más comunes son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arquitectura incompatible&lt;/strong&gt;: La imagen fue construida para &lt;code&gt;amd64&lt;/code&gt; (x86_64), pero Raspberry Pi usa &lt;code&gt;armhf&lt;/code&gt; o &lt;code&gt;arm64&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Falta de binarios nativos&lt;/strong&gt;: El &lt;code&gt;ENTRYPOINT&lt;/code&gt;/&lt;code&gt;CMD&lt;/code&gt; del contenedor intenta ejecutar un binario compilado para otra arquitectura.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Problemas de permisos en dispositivos del sistema&lt;/strong&gt; (especialmente en Raspberry Pi OS Lite o sin entorno gráfico).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Falta de memoria o recursos insuficientes&lt;/strong&gt; (menos común, pero posible en dispositivos con poca RAM).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;El hecho de que funcione en una VM pero no en hardware físico confirma fuertemente un problema de arquitectura.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pasos para solucionarlo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Verifica la arquitectura del host y de la imagen
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# En tu Raspberry Pi:&lt;/span&gt;
&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;
&lt;span class="c"&gt;# Salida esperada: armv7l (32-bit) o aarch64 (64-bit)&lt;/span&gt;

docker images myimage
&lt;span class="c"&gt;# Busca la columna "ARCHITECTURE" (si está disponible)&lt;/span&gt;

docker inspect myimage | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; architecture
&lt;span class="c"&gt;# Salida esperada: "Architecture": "arm" o "arm64"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Si la imagen no es compatible: reconstrúyela para ARM
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Opción A: Usa &lt;code&gt;docker buildx&lt;/code&gt; (recomendado)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Habilita buildx&lt;/span&gt;
docker buildx create &lt;span class="nt"&gt;--use&lt;/span&gt;

&lt;span class="c"&gt;# Construye para la arquitectura correcta&lt;/span&gt;
docker buildx build &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--platform&lt;/span&gt; linux/arm/v7,linux/arm64 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--push&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-t&lt;/span&gt; tu-usuario/myimage:latest &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ Si tu imagen depende de binarios nativos (ej. &lt;code&gt;.so&lt;/code&gt;, ejecutables precompilados), asegúrate de que estén disponibles para ARM.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Opción B: Usa una imagen base compatible
&lt;/h4&gt;

&lt;p&gt;En tu &lt;code&gt;Dockerfile&lt;/code&gt;, cambia la imagen base a una versión ARM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# En lugar de:&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:18-alpine&lt;/span&gt;

&lt;span class="c"&gt;# Usa:&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; arm32v7/node:18-alpine   # Para Raspberry Pi 3/4 32-bit&lt;/span&gt;
&lt;span class="c"&gt;# O&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; arm64v8/node:18-alpine   # Para Raspberry Pi 4/5 64-bit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Ejecuta en primer plano para diagnosticar
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
&lt;span class="c"&gt;# Quita la opción -d para ver logs en tiempo real&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si ves errores como &lt;code&gt;Exec format error&lt;/code&gt;, es &lt;strong&gt;confirmación definitiva&lt;/strong&gt; de incompatibilidad de arquitectura.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Verifica que el comando de inicio sea válido
&lt;/h3&gt;

&lt;p&gt;Algunas imágenes usan &lt;code&gt;ENTRYPOINT&lt;/code&gt; que requiere shell. Si el contenedor falla por &lt;code&gt;no such file or directory&lt;/code&gt;, agrega &lt;code&gt;--entrypoint=/bin/sh&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nt"&gt;--entrypoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/bin/sh myimage &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"echo 'test' &amp;amp;&amp;amp; ls -la /"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Bloque de código corregido (ejemplo funcional)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Dockerfile corregido para Raspberry Pi&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; arm32v7/python:3.9-slim&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Asegura que el script sea ejecutable&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /app/start.sh

&lt;span class="c"&gt;# Usa shell para evitar problemas de PATH&lt;/span&gt;
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["/bin/sh", "-c", "/app/start.sh"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y luego:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Construcción para ARM&lt;/span&gt;
docker buildx build &lt;span class="nt"&gt;--platform&lt;/span&gt; linux/arm/v7 &lt;span class="nt"&gt;-t&lt;/span&gt; myimage:latest &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Ejecución corregida (sin espacios en `--net=host`)&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🔥 &lt;strong&gt;Nota crítica&lt;/strong&gt;: En tu comando original hay un error tipográfico: &lt;code&gt;--net = host&lt;/code&gt; (con espacios) es inválido. Debe ser &lt;code&gt;--net=host&lt;/code&gt; (sin espacios alrededor del &lt;code&gt;=&lt;/code&gt;).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Pro-tip: Diagnóstico rápido con &lt;code&gt;docker run --rm&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-t&lt;/span&gt; myimage 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;tee&lt;/span&gt; /tmp/container.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto ejecuta el contenedor en primer plano, lo elimina automáticamente al terminar (&lt;code&gt;--rm&lt;/code&gt;) y guarda los logs para análisis.&lt;/p&gt;

&lt;p&gt;Si el problema persiste, revisa:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;dmesg | grep -i segfault&lt;/code&gt; (para detectar fallos de segmentación por arquitectura)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;file /usr/bin/python3&lt;/code&gt; dentro del contenedor (si puedes acceder con &lt;code&gt;--entrypoint=/bin/sh&lt;/code&gt;) para confirmar arquitectura del binario.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>linux</category>
    </item>
    <item>
      <title>Cómo solucionar el error “Enable JavaScript and cookies to continue”</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Thu, 06 Aug 2026 11:14:28 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-error-enable-javascript-and-cookies-to-continue-2692</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-error-enable-javascript-and-cookies-to-continue-2692</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el error “Enable JavaScript and cookies to continue”
&lt;/h1&gt;

&lt;p&gt;Este error aparece cuando &lt;strong&gt;Cloudflare&lt;/strong&gt; (u otro proxy inverso de seguridad) bloquea la solicitud del cliente porque detecta que &lt;strong&gt;JavaScript está deshabilitado o no se ha completado el desafío de verificación&lt;/strong&gt; (como un &lt;em&gt;browser integrity check&lt;/em&gt;). No es un error de tu código front-end, sino un mecanismo de seguridad activo.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 Causa técnica
&lt;/h2&gt;

&lt;p&gt;Cloudflare (o similar, como AWS WAF + Bot Management) inyecta un desafío JavaScript en la respuesta inicial. Si el navegador no ejecuta ese script (porque JS está deshabilitado, bloqueado por adblockers, o el entorno no es un navegador real), el servidor responde con este mensaje y niega el acceso.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Casos comunes donde ocurre:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pruebas automatizadas con &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;requests&lt;/code&gt; de Python, o herramientas headless sin emular JS.&lt;/li&gt;
&lt;li&gt;Navegadores con JavaScript deshabilitado o bloqueado.&lt;/li&gt;
&lt;li&gt;Uso de extensiones que bloquean scripts (uBlock Origin, NoScript).&lt;/li&gt;
&lt;li&gt;Configuración incorrecta de &lt;code&gt;User-Agent&lt;/code&gt; o cabeceras HTTP que activan reglas de bloqueo.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✅ Solución definitiva (por escenario)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🧪 1. Si estás haciendo pruebas automatizadas (Python, Node.js, etc.)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;No uses &lt;code&gt;requests&lt;/code&gt; o &lt;code&gt;curl&lt;/code&gt; directamente.&lt;/strong&gt; Necesitas un motor de navegador real que ejecute JS.&lt;/p&gt;

&lt;h4&gt;
  
  
  ✅ Opción recomendada: Playwright (soporta bypass de Cloudflare)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;playwright
playwright &lt;span class="nb"&gt;install &lt;/span&gt;chromium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Ejemplo en Python con Playwright
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;playwright.sync_api&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sync_playwright&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;sync_playwright&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;headless&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new_context&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new_page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://tu-sitio.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Espera a que se resuelva el desafío (Cloudflare lo maneja automáticamente si el navegador es real)
&lt;/span&gt;    &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_load_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;networkidle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  &lt;span class="c1"&gt;# Ya estás dentro
&lt;/span&gt;    &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Importante&lt;/strong&gt;: Usa &lt;code&gt;headless=False&lt;/code&gt; en pruebas iniciales para verificar. En producción, puedes usar &lt;code&gt;headless=True&lt;/code&gt; con &lt;code&gt;args=["--disable-blink-features=AutomationControlled"]&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  ❌ Evita: &lt;code&gt;requests&lt;/code&gt; + &lt;code&gt;cloudscraper&lt;/code&gt; (inestable y fácilmente detectado)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# NO RECOMENDADO: cloudscraper es frágil y se rompe con actualizaciones de Cloudflare
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cloudscraper&lt;/span&gt;
&lt;span class="n"&gt;scraper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cloudscraper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_scraper&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scraper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://tu-sitio.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Puede fallar en segundos
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🌐 2. Si eres usuario final (no desarrollador)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Habilita JavaScript&lt;/strong&gt; en tu navegador:

&lt;ul&gt;
&lt;li&gt;Chrome: &lt;code&gt;Configuración → Privacidad y seguridad → Configuración del sitio → JavaScript → Permitido&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Firefox: &lt;code&gt;Preferencias → Privacidad y seguridad → Permisos → Habilitar JavaScript&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Desactiva temporalmente bloqueadores de anuncios&lt;/strong&gt; (uBlock, AdGuard).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limpia cookies y caché&lt;/strong&gt; → vuelve a cargar la página.&lt;/li&gt;
&lt;li&gt;Usa un navegador actualizado (Chrome/Firefox/Edge última versión estable).&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🛠️ 3. Si eres administrador del sitio (configuración Cloudflare)
&lt;/h3&gt;

&lt;p&gt;Si el desafío es innecesario para tu tráfico legítimo:&lt;/p&gt;

&lt;h4&gt;
  
  
  Opción A: Ajustar nivel de protección de bots
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;En Cloudflare Dashboard → &lt;strong&gt;Security → Bot Management&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Cambia &lt;strong&gt;Bot Fight Mode&lt;/strong&gt; a &lt;code&gt;Off&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;En &lt;strong&gt;Challenge Passage&lt;/strong&gt;, añade reglas para excluir IPs o rutas confiables.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Opción B: Deshabilitar temporalmente el modo "Under Attack"
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Dashboard → &lt;strong&gt;Security → WAF&lt;/strong&gt; → Cambia el modo de &lt;strong&gt;Under Attack&lt;/strong&gt; a &lt;strong&gt;Essential&lt;/strong&gt; o &lt;strong&gt;Low&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Nunca deshabilites completamente Cloudflare&lt;/strong&gt; si tu sitio es público. Usa excepciones selectivas.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  💡 Pro-tip: Detecta si Cloudflare está bloqueando tu petición
&lt;/h2&gt;

&lt;p&gt;Agrega esta cabecera en tus peticiones para ver el &lt;em&gt;ray ID&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; https://tu-sitio.com 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"cf-ray"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si aparece &lt;code&gt;cf-ray&lt;/code&gt;, Cloudflare está interviniendo. Si la respuesta es &lt;code&gt;&amp;lt;div class="h2"&amp;gt;...Enable JavaScript...&amp;lt;/div&amp;gt;&lt;/code&gt;, el desafío no se completó.&lt;/p&gt;




&lt;p&gt;✅ &lt;strong&gt;Resultado esperado&lt;/strong&gt;: Al usar un navegador real (Playwright/Selenium con Chrome) o ajustar configuraciones de seguridad, el error desaparece y la página carga correctamente.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Cómo solucionar `docker run` con error `Exited (1)` en Raspberry Pi</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Wed, 05 Aug 2026 11:14:19 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-docker-run-con-error-exited-1-en-raspberry-pi-153</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-docker-run-con-error-exited-1-en-raspberry-pi-153</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar &lt;code&gt;docker run&lt;/code&gt; con error &lt;code&gt;Exited (1)&lt;/code&gt; en Raspberry Pi
&lt;/h1&gt;

&lt;h2&gt;
  
  
  ¿Por qué ocurre este error?
&lt;/h2&gt;

&lt;p&gt;El código de salida &lt;code&gt;1&lt;/code&gt; indica que el proceso principal del contenedor terminó con un error genérico. En Raspberry Pi (especialmente modelos con arquitectura ARM), los problemas más comunes son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Incompatibilidad de arquitectura&lt;/strong&gt;: La imagen fue construida para &lt;code&gt;amd64&lt;/code&gt; (x86_64) pero se ejecuta en ARM (&lt;code&gt;armv7l&lt;/code&gt; o &lt;code&gt;aarch64&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Falta de binarios compatibles&lt;/strong&gt;: El &lt;code&gt;ENTRYPOINT&lt;/code&gt; o &lt;code&gt;CMD&lt;/code&gt; del contenedor intenta ejecutar un binario incompatible con ARM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Problemas de permisos o recursos&lt;/strong&gt;: Falta de acceso a dispositivos (GPIO, etc.) o memoria insuficiente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Espacio en disco insuficiente&lt;/strong&gt;: Raspberry Pi suele tener particiones pequeñas para &lt;code&gt;/var/lib/docker&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🔍 &lt;strong&gt;Nota crítica&lt;/strong&gt;: En tu comando &lt;code&gt;docker run --net = host&lt;/code&gt;, hay un &lt;strong&gt;espacio innecesario y problemático&lt;/strong&gt; después del &lt;code&gt;--net&lt;/code&gt;. Docker lo interpreta como un nombre de red literal &lt;code&gt;= host&lt;/code&gt;, lo que causa fallos silenciosos o errores de red.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Pasos para solucionarlo (ordenados por probabilidad de éxito en Raspberry Pi)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Corrige el comando: elimina espacios en &lt;code&gt;--net = host&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ❌ INCORRECTO (espacios alrededor del '=')&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage

&lt;span class="c"&gt;# ✅ CORRECTO (sin espacios)&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Verifica la arquitectura de la imagen y del host
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# En tu Raspberry Pi:&lt;/span&gt;
&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;  &lt;span class="c"&gt;# Debería mostrar: armv7l (RPi 3/4) o aarch64 (RPi 4/5)&lt;/span&gt;

&lt;span class="c"&gt;# Verifica la arquitectura de tu imagen:&lt;/span&gt;
docker inspect myimage | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nb"&gt;arch&lt;/span&gt;
&lt;span class="c"&gt;# O directamente:&lt;/span&gt;
docker images &lt;span class="nt"&gt;--format&lt;/span&gt; &lt;span class="s2"&gt;"{{.Architecture}}"&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si la imagen es &lt;code&gt;amd64&lt;/code&gt; y tu Pi es ARM, &lt;strong&gt;necesitas reconstruir la imagen para ARM&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Ejecuta en primer plano para ver el error real
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; myimage
&lt;span class="c"&gt;# O sin -d (background) ni -t (TTY):&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt; host myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto mostrará el error específico (ej: &lt;code&gt;standard_init_linux.go:211: exec user process caused: no such file or directory&lt;/code&gt; → indica binario incompatible).&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Solución definitiva: reconstruir imagen para ARM
&lt;/h3&gt;

&lt;p&gt;Si usas &lt;code&gt;Dockerfile&lt;/code&gt;, añade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Al inicio del Dockerfile&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; --platform=linux/arm/v7 arm32v7/debian:bullseye-slim  # o la base que uses&lt;/span&gt;
&lt;span class="c"&gt;# O para RPi 4/5 de 64 bits:&lt;/span&gt;
&lt;span class="c"&gt;# FROM --platform=linux/arm64 arm64v8/debian:bullseye-slim&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y reconstruye:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; myimage &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Verifica espacio en disco y permisos
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Espacio en disco:&lt;/span&gt;
&lt;span class="nb"&gt;df&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; /var/lib/docker

&lt;span class="c"&gt;# Si es crítico (&amp;lt; 500 MB), limpia:&lt;/span&gt;
docker system prune &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;--volumes&lt;/span&gt;

&lt;span class="c"&gt;# Si el contenedor necesita acceso a hardware (GPIO, etc.):&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;--privileged&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Bloque de código corregido (ejemplo funcional en RPi)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Verifica arquitectura&lt;/span&gt;
&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;

&lt;span class="c"&gt;# 2. Corrige el comando (¡sin espacios en --net!)&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage

&lt;span class="c"&gt;# 3. Si persiste el error, ejecuta en foreground para debug:&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; myimage

&lt;span class="c"&gt;# 4. Si necesitas acceso a dispositivos (opcional):&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;--device&lt;/span&gt; /dev/gpiomem &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Pro-tip: Usa &lt;code&gt;docker run --platform&lt;/code&gt; para forzar compatibilidad (si la imagen lo soporta)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Si tu imagen es multi-plataforma (multi-arch):&lt;/span&gt;
docker run &lt;span class="nt"&gt;--platform&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux/arm/v7 &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Importante&lt;/strong&gt;: Solo funciona si el repositorio de la imagen tiene manifests multi-arch (ej: &lt;code&gt;python:3.9&lt;/code&gt;, &lt;code&gt;nginx&lt;/code&gt;, etc.). Si no, tendrás que reconstruir.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;strong&gt;Resumen rápido&lt;/strong&gt;:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Elimina espacios en &lt;code&gt;--net host&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Verifica arquitectura (&lt;code&gt;uname -m&lt;/code&gt; vs &lt;code&gt;docker inspect&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Ejecuta sin &lt;code&gt;-d&lt;/code&gt; para ver el error
&lt;/li&gt;
&lt;li&gt;Reconstruye la imagen para ARM si es necesario
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Con esto, el contenedor dejará de salir con &lt;code&gt;Exited (1)&lt;/code&gt; en tu Raspberry Pi.&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>docker</category>
      <category>linux</category>
      <category>raspberrypi</category>
    </item>
    <item>
      <title>Cómo solucionar `docker run` con exit code 1 en Raspberry Pi</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Tue, 04 Aug 2026 11:17:55 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-docker-run-con-exit-code-1-en-raspberry-pi-4oan</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-docker-run-con-exit-code-1-en-raspberry-pi-4oan</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar &lt;code&gt;docker run&lt;/code&gt; con exit code 1 en Raspberry Pi
&lt;/h1&gt;

&lt;h2&gt;
  
  
  ¿Por qué ocurre?
&lt;/h2&gt;

&lt;p&gt;El error &lt;code&gt;Exited (1)&lt;/code&gt; indica que el proceso principal del contenedor terminó con un código de error. En Raspberry Pi, los casos más comunes son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arquitectura incompatible&lt;/strong&gt;: La imagen fue construida para &lt;code&gt;amd64&lt;/code&gt; (x86_64) pero Raspberry Pi usa &lt;code&gt;armhf&lt;/code&gt; o &lt;code&gt;arm64&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Falta de binarios compatibles&lt;/strong&gt;: El &lt;code&gt;ENTRYPOINT&lt;/code&gt;/&lt;code&gt;CMD&lt;/code&gt; del contenedor ejecuta un binario compilado para otra arquitectura.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Problemas de permisos o recursos&lt;/strong&gt;: Especialmente en Raspberry Pi con sistemas minimalistas (Raspbian/Debian).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sintaxis inválida en el comando&lt;/strong&gt;: El espacio en &lt;code&gt;--net = host&lt;/code&gt; es un error grave.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pasos para solucionarlo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Corrige la sintaxis del comando
&lt;/h3&gt;

&lt;p&gt;El comando original tiene un error crítico: &lt;code&gt;--net = host&lt;/code&gt; &lt;strong&gt;debe escribirse sin espacios alrededor del &lt;code&gt;=&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# INCORRECTO (genera error de parsing)&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage

&lt;span class="c"&gt;# CORRECTO&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Ejecuta en primer plano para ver el error real
&lt;/h3&gt;

&lt;p&gt;Elimina &lt;code&gt;-d&lt;/code&gt; (modo detached) y añade &lt;code&gt;-it&lt;/code&gt; para ver el output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;-it&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Verifica la arquitectura del contenedor
&lt;/h3&gt;

&lt;p&gt;Ejecuta estos comandos en tu Raspberry Pi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Verifica la arquitectura del host&lt;/span&gt;
&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;

&lt;span class="c"&gt;# Verifica la arquitectura de la imagen&lt;/span&gt;
docker inspect myimage | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; architecture
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si la imagen es &lt;code&gt;amd64&lt;/code&gt; y tu Pi es &lt;code&gt;armv7l&lt;/code&gt; o &lt;code&gt;aarch64&lt;/code&gt;, &lt;strong&gt;no funcionará&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Usa imágenes multiarquitectura o reconstruye
&lt;/h3&gt;

&lt;p&gt;Si la imagen no es compatible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Opción A: Busca una versión ARM de la imagen&lt;/span&gt;
docker pull arm32v7/nginx     &lt;span class="c"&gt;# Ejemplo para ARMv7&lt;/span&gt;
docker pull arm64v8/nginx     &lt;span class="c"&gt;# Ejemplo para ARM64&lt;/span&gt;

&lt;span class="c"&gt;# Opción B: Reconstruye la imagen en el Pi&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; myimage &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Verifica dependencias críticas
&lt;/h3&gt;

&lt;p&gt;En Raspberry Pi, asegúrate de tener instalados:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; libseccomp2 libsystemd0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bloque de código corregido
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Comando corregido + diagnóstico&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; myimage

&lt;span class="c"&gt;# Si falla por arquitectura, usa QEMU para emulación (lento)&lt;/span&gt;
docker run &lt;span class="nt"&gt;--platform&lt;/span&gt; linux/arm/v7 &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Nota crítica&lt;/strong&gt;: Si usas &lt;code&gt;--platform linux/arm/v7&lt;/code&gt;, necesitas habilitar QEMU en Docker:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--privileged&lt;/span&gt; multiarch/qemu-user-static &lt;span class="nt"&gt;--reset&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nb"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Pro-tip: Diagnóstico rápido en Raspberry Pi
&lt;/h2&gt;

&lt;p&gt;Crea este script de diagnóstico:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=== ARQUITECTURA DEL HOST ==="&lt;/span&gt;
&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;=== ARQUITECTURA DE LA IMAGEN ==="&lt;/span&gt;
docker inspect myimage &lt;span class="nt"&gt;--format&lt;/span&gt; &lt;span class="s1"&gt;'{{.Architecture}}'&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;=== LOGS DEL CONTENEDOR ==="&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;-d&lt;/span&gt; myimage
&lt;span class="nb"&gt;sleep &lt;/span&gt;2
docker logs &lt;span class="si"&gt;$(&lt;/span&gt;docker ps &lt;span class="nt"&gt;-lq&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este script te dará la causa raíz en menos de 30 segundos.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>linux</category>
    </item>
    <item>
      <title>Cómo solucionar el error “Enable JavaScript and cookies to continue”</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Mon, 03 Aug 2026 12:15:20 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-error-enable-javascript-and-cookies-to-continue-fbd</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-error-enable-javascript-and-cookies-to-continue-fbd</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el error “Enable JavaScript and cookies to continue”
&lt;/h1&gt;

&lt;p&gt;Este error aparece cuando &lt;strong&gt;Cloudflare&lt;/strong&gt; (u otro proxy inverso de seguridad) detecta que el navegador del usuario no cumple con los requisitos mínimos para acceder al sitio: &lt;strong&gt;JavaScript está deshabilitado o las cookies no están permitidas&lt;/strong&gt;. Pero en entornos reales, el problema suele ser más sutil: el navegador &lt;em&gt;sí&lt;/em&gt; tiene JS y cookies habilitados, pero &lt;strong&gt;la configuración del entorno de ejecución (como un headless browser, test automation, o un scraper) no emula correctamente el comportamiento del cliente&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 Causa raíz técnica
&lt;/h2&gt;

&lt;p&gt;Cloudflare emite un desafío (CAPTCHA o JS challenge) para verificar que el cliente es un navegador real. Si la respuesta no cumple con el desafío (por ejemplo, porque:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El navegador no ejecuta el JS del desafío (headless sin soporte),&lt;/li&gt;
&lt;li&gt;Las cookies no se persisten entre solicitudes,&lt;/li&gt;
&lt;li&gt;El &lt;code&gt;User-Agent&lt;/code&gt; o &lt;code&gt;Accept-Language&lt;/code&gt; no coinciden con navegadores reales,&lt;/li&gt;
&lt;li&gt;Falta el &lt;code&gt;Referer&lt;/code&gt; o &lt;code&gt;Origin&lt;/code&gt; en headers,&lt;/li&gt;
&lt;li&gt;Se bloquean cookies de terceros (como las de Cloudflare),&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;… entonces el servidor devuelve este mensaje estático en lugar de redirigir a la página solicitada.&lt;/p&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Nota crítica&lt;/strong&gt;: Si estás usando herramientas como &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;requests&lt;/code&gt; de Python, o navegadores headless sin configuración especial, &lt;strong&gt;no pasarás el desafío de Cloudflare&lt;/strong&gt;. Es intencional: Cloudflare bloquea tráfico no humano por diseño.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Solución definitiva (por escenario)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🛠️ Caso 1: Navegador real (usuario final)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Verifica que JavaScript esté habilitado&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Chrome: &lt;code&gt;Configuración → Privacidad y seguridad → Configuración de sitios → JavaScript → Permitido&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Firefox: &lt;code&gt;Preferencias → Privacidad y seguridad → Cookies y datos de sitios → Deshabilitar “Bloquear cookies y datos de sitios”&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limpia cookies y caché&lt;/strong&gt; (especialmente para &lt;code&gt;*.cloudflare.com&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reinicia el navegador&lt;/strong&gt; y vuelve a cargar la página.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🛠️ Caso 2: Automatización / Scraping (Python + Playwright/Selenium)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;No uses &lt;code&gt;requests&lt;/code&gt; o &lt;code&gt;urllib&lt;/code&gt;&lt;/strong&gt;: no ejecutan JS. Usa un navegador real con soporte para Cloudflare.&lt;/p&gt;

&lt;h4&gt;
  
  
  ✅ Ejemplo con &lt;strong&gt;Playwright&lt;/strong&gt; (recomendado):
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;playwright.sync_api&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sync_playwright&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;sync_playwright&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;headless&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# headless=True también funciona si se configura bien
&lt;/span&gt;    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;viewport&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;width&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;height&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1080&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;user_agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new_page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Opcional: simular interacción humana para evitar bloqueos
&lt;/span&gt;    &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://tu-sitio.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wait_until&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;networkidle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Espera explícita al desafío Cloudflare y su resolución automática
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#challenge-error-text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cloudflare bloqueó la solicitud. Asegúrate de usar un navegador real.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;  &lt;span class="c1"&gt;# No hay desafío → todo bien
&lt;/span&gt;
    &lt;span class="c1"&gt;# Procede con la navegación
&lt;/span&gt;    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  🔑 Claves:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Usa &lt;code&gt;wait_until="networkidle"&lt;/code&gt; para esperar a que termine todo el JS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nunca uses &lt;code&gt;headless="new"&lt;/code&gt; sin configuración extra&lt;/strong&gt;: Cloudflare detecta headless moderno fácilmente.&lt;/li&gt;
&lt;li&gt;Si usas &lt;code&gt;headless=True&lt;/code&gt;, añade:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="c1"&gt;# ... otros parámetros ...
&lt;/span&gt;      &lt;span class="n"&gt;bypass_csp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Evita bloqueos de Content Security Policy
&lt;/span&gt;      &lt;span class="n"&gt;java_script_enabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cf_clearance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;domain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.tu-sitio.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;  &lt;span class="c1"&gt;# Si ya tienes un clearance válido
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🛠️ Caso 3: App móvil / WebView (Android/iOS)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;En Android: Asegúrate de que &lt;code&gt;WebView.getSettings().setJavaScriptEnabled(true)&lt;/code&gt; y &lt;code&gt;setAcceptCookies(true)&lt;/code&gt; estén activos.&lt;/li&gt;
&lt;li&gt;En iOS: Verifica que &lt;code&gt;WKWebView&lt;/code&gt; tenga &lt;code&gt;dataStore = WKWebsiteDataStore.default()&lt;/code&gt; (para persistir cookies).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 Verificación rápida (CLI)
&lt;/h2&gt;

&lt;p&gt;Si quieres probar si el sitio responde sin desafío:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Accept: text/html,application/xhtml+xml"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Accept-Language: es-ES,es;q=0.9"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Referer: https://www.google.com/"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-c&lt;/span&gt; /tmp/cookies.txt &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-L&lt;/span&gt; https://tu-sitio.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si el HTML contiene &lt;code&gt;#challenge-error-text&lt;/code&gt;, &lt;strong&gt;el servidor sigue bloqueando&lt;/strong&gt;. Necesitas emular un navegador real.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Pro-tip: Evita el desafío desde el origen
&lt;/h2&gt;

&lt;p&gt;Si tú controlas el backend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agrega tu IP o rango a la lista blanca de Cloudflare&lt;/strong&gt; (Panel → Firewall → Tools → Add IP Address).&lt;/li&gt;
&lt;li&gt;Usa &lt;strong&gt;Cloudflare Access&lt;/strong&gt; con autenticación por token si es una API interna.&lt;/li&gt;
&lt;li&gt;Para APIs públicas: &lt;strong&gt;desactiva el "Under Attack Mode"&lt;/strong&gt; y ajusta las reglas de WAF para excluir endpoints de API.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Nunca intentes "bypassear" Cloudflare sin autorización&lt;/strong&gt;. Es una violación de sus Términos y puede generar bloqueos permanentes.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;✅ &lt;strong&gt;Solución definitiva resumida&lt;/strong&gt;: Usa un navegador real (Playwright/Selenium) con cookies habilitadas, &lt;code&gt;User-Agent&lt;/code&gt; realista y espera a que termine el JS. Si eres el propietario del sitio, configura Cloudflare para excluir tráfico legítimo.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>javascript</category>
      <category>security</category>
      <category>webscraping</category>
    </item>
    <item>
      <title>Cómo solucionar \"Text content does not match server-rendered HTML\" en Next.js App Router</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Sun, 02 Aug 2026 10:28:25 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-text-content-does-not-match-server-rendered-html-en-nextjs-app-router-4f0m</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-text-content-does-not-match-server-rendered-html-en-nextjs-app-router-4f0m</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar "Text content does not match server-rendered HTML" en Next.js App Router
&lt;/h1&gt;

&lt;p&gt;Este error ocurre cuando el HTML generado en el servidor (SSR/SSG) no coincide con lo que React intenta hidratar en el navegador. Es un problema de &lt;strong&gt;coherencia entre el DOM estático y el árbol virtual inicial&lt;/strong&gt;, no un error de lógica funcional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Causa raíz técnica
&lt;/h2&gt;

&lt;p&gt;La mayoría de los casos provienen de &lt;strong&gt;código no determinista en tiempo de renderizado&lt;/strong&gt;, como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uso directo de &lt;code&gt;window&lt;/code&gt;, &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;Date.now()&lt;/code&gt; o &lt;code&gt;new Date()&lt;/code&gt; en el render&lt;/li&gt;
&lt;li&gt;Lógica condicional basada en &lt;code&gt;typeof window !== 'undefined'&lt;/code&gt; &lt;em&gt;dentro&lt;/em&gt; del render&lt;/li&gt;
&lt;li&gt;APIs del navegador que no existen en Node.js&lt;/li&gt;
&lt;li&gt;Extensiones del navegador (especialmente en desarrollo) que inyectan elementos&lt;/li&gt;
&lt;li&gt;Metaetiquetas de iOS que transforman automáticamente contenido (ej. números telefónicos → enlaces)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Solución definitiva (pasos verificados)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Paso 1: Identifica el elemento problemático
&lt;/h3&gt;

&lt;p&gt;Busca en el stack trace o en la consola del navegador el mensaje exacto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Warning: Text content "..." does not match server-rendered "..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Localiza el componente y el elemento HTML afectado.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Paso 2: Aplica la solución según el caso
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Caso A: Contenido dinámico (fechas, IDs aleatorios, etc.)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Usa &lt;code&gt;suppressHydrationWarning&lt;/code&gt; en el elemento específico:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Mal: fecha generada en render&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Bien: con supresión explícita&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt; &lt;span class="na"&gt;suppressHydrationWarning&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Caso B: Uso de APIs del navegador (localStorage, window.innerWidth, etc.)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Mueve la lógica a &lt;code&gt;useEffect&lt;/code&gt; o usa &lt;code&gt;dynamic({ ssr: false })&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Mal: acceso directo a window&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setWidth&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Bien: con useEffect + estado inicial seguro&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Responsive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setWidth&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Inicializa con valor neutral&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleResize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleResize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleResize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Width: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Caso C: Componente 100% client-side (ej. gráficos, canvas, mapas)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Desactiva SSR con &lt;code&gt;next/dynamic&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/MapChart.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MapChart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Código que usa window, document, etc.&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mapRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// page.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dynamic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/dynamic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MapChart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/MapChart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="na"&gt;ssr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Cargando mapa...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MapChart&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ Paso 3: Verifica configuraciones externas
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Desactiva extensiones del navegador&lt;/strong&gt; (especialmente ad-blockers, traductores, lectores de pantalla)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revisa configuraciones de CDN/Edge&lt;/strong&gt; (Cloudflare Auto Minify, Fastly Edge Side Includes)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agrega metaetiqueta para iOS&lt;/strong&gt; si usas fechas/teléfonos:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- en app/layout.tsx --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"format-detection"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"telephone=no, date=no, email=no"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pro-tip: Diagnóstico rápido con &lt;code&gt;console.log&lt;/code&gt; en SSR
&lt;/h2&gt;

&lt;p&gt;Agrega esto temporalmente en el componente sospechoso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SERVER RENDER:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CLIENT RENDER:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si los logs difieren en estructura o contenido, ahí está el problema.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Nunca uses &lt;code&gt;suppressHydrationWarning&lt;/code&gt; en elementos contenedores&lt;/strong&gt; (como &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; genéricos). Solo en elementos &lt;em&gt;específicos&lt;/em&gt; con contenido no determinista (ej. &lt;code&gt;&amp;lt;time&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; con timestamp).&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>javascript</category>
      <category>nextjs</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Cómo solucionar el error \"Enable JavaScript and cookies to continue\"</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Sat, 01 Aug 2026 10:29:05 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-error-enable-javascript-and-cookies-to-continue-5bgp</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-error-enable-javascript-and-cookies-to-continue-5bgp</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el error "Enable JavaScript and cookies to continue"
&lt;/h1&gt;

&lt;h2&gt;
  
  
  ¿Por qué ocurre este error?
&lt;/h2&gt;

&lt;p&gt;Este mensaje aparece cuando &lt;strong&gt;Cloudflare&lt;/strong&gt; (o un proxy similar como AWS WAF, Akamai, etc.) detecta que el navegador del cliente &lt;strong&gt;no cumple con los requisitos mínimos de seguridad&lt;/strong&gt; para acceder al sitio protegido. Específicamente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript está deshabilitado o bloqueado (por extensiones, configuraciones de seguridad o navegadores antiguos).&lt;/li&gt;
&lt;li&gt;Las cookies no están habilitadas o no se están aceptando correctamente.&lt;/li&gt;
&lt;li&gt;El navegador no pasa el &lt;em&gt;JavaScript Challenge&lt;/em&gt; de Cloudflare (un mecanismo anti-bot que verifica que el cliente es un navegador real).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Importante&lt;/strong&gt;: Este error &lt;strong&gt;no es un bug en tu código front-end&lt;/strong&gt;. Es una defensa del servidor/proxy contra tráfico no confiable. Pero si tú eres el desarrollador y ves este mensaje &lt;em&gt;mientras desarrollas localmente&lt;/em&gt;, entonces sí es un problema de configuración.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pasos para resolverlo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Caso 1: Estás probando localmente (localhost)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Verifica que no estés usando &lt;code&gt;file://&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Cloudflare y otros WAF &lt;strong&gt;no funcionan con archivos locales&lt;/strong&gt; (&lt;code&gt;file://&lt;/code&gt;). Debes servir tu sitio mediante un servidor HTTP local (ej. &lt;code&gt;http://localhost:3000&lt;/code&gt;).&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Usa un servidor local con HTTPS (recomendado)
&lt;/h4&gt;

&lt;p&gt;Cloudflare requiere HTTPS para muchos desafíos. Configura tu entorno local con HTTPS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;En Next.js: &lt;code&gt;next dev --https&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;En Vite: Usa &lt;code&gt;vite --https&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;En Node puro: Usa &lt;code&gt;mkcert&lt;/code&gt; + &lt;code&gt;http-server&lt;/code&gt; con certificados locales firmados.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Desactiva temporalmente Cloudflare (si estás usando su proxy)
&lt;/h4&gt;

&lt;p&gt;Si usas Cloudflare en desarrollo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ve a la pestaña &lt;strong&gt;DNS&lt;/strong&gt; en tu panel de Cloudflare.&lt;/li&gt;
&lt;li&gt;Asegúrate de que el registro de tu dominio tenga el ícono &lt;strong&gt;nube gris&lt;/strong&gt; (DNS only), &lt;strong&gt;NO naranja&lt;/strong&gt; (proxied).&lt;/li&gt;
&lt;li&gt;O usa un dominio sin proxy para desarrollo (ej. &lt;code&gt;dev.tudominio.com&lt;/code&gt; sin proxy).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. Verifica que tu navegador no bloquee cookies o JS
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Desactiva extensiones como uBlock Origin, Privacy Badger, Ghostery.&lt;/li&gt;
&lt;li&gt;Asegúrate de que &lt;code&gt;javascript.enabled = true&lt;/code&gt; y &lt;code&gt;network.cookie.cookieBehavior = 0&lt;/code&gt; (en &lt;code&gt;about:config&lt;/code&gt; de Firefox o Chrome).&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  ✅ Caso 2: El error ocurre en producción (usuarios reales)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Verifica que el dominio esté correctamente configurado en Cloudflare
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Asegúrate de que el registro DNS apunte a Cloudflare y que el proxy esté activo (nube naranja).&lt;/li&gt;
&lt;li&gt;Confirma que el certificado SSL esté activo (Flexible/Full/Full (Strict)).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. Ajusta el nivel de protección de Cloudflare
&lt;/h4&gt;

&lt;p&gt;Ve a &lt;strong&gt;Security → WAF → Tools&lt;/strong&gt; y revisa:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Browser Integrity Check&lt;/strong&gt;: Si está en &lt;em&gt;High&lt;/em&gt;, baja a &lt;em&gt;Medium&lt;/em&gt; o &lt;em&gt;Low&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Challenge Passage&lt;/strong&gt;: Verifica que no estés bloqueando por User-Agent o IP.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Asegura que tu app envíe cookies correctamente
&lt;/h4&gt;

&lt;p&gt;Si usas autenticación:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Las cookies deben tener &lt;code&gt;SameSite=None&lt;/code&gt; y &lt;code&gt;Secure&lt;/code&gt; si se usan en subdominios o con HTTPS.&lt;/li&gt;
&lt;li&gt;Ejemplo en Node.js/Express:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abc123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;httpOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// obligatorio para SameSite=None&lt;/span&gt;
    &lt;span class="na"&gt;sameSite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;None&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.tudominio.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Verifica que no haya CORS mal configurado
&lt;/h4&gt;

&lt;p&gt;Si el frontend y backend están en dominios distintos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El backend debe enviar &lt;code&gt;Access-Control-Allow-Credentials: true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;El frontend debe usar &lt;code&gt;credentials: 'include'&lt;/code&gt; en &lt;code&gt;fetch&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;include&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pass&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Bloque de código corregido (ejemplo mínimo funcional)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"es"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;App segura&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// Asegura que JS esté habilitado (opcional, para UX)&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;JavaScript está activo ✅&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Cargando...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// Verificación básica de cookies (para depuración)&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;session=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;⚠️ Cookies no detectadas. Verifica configuración.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Pro-tip: Diagnóstico rápido con &lt;code&gt;curl&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Ejecuta esto en tu terminal para simular una petición limpia:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; https://tudominio.com 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"challenge&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;set-cookie&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;javascript"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Si ves &lt;code&gt;&amp;lt; set-cookie: cf_clearance=...&lt;/code&gt;, Cloudflare está emitiendo el challenge.&lt;/li&gt;
&lt;li&gt;Si no hay &lt;code&gt;set-cookie&lt;/code&gt;, el problema está en la configuración del proxy o certificado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ &lt;strong&gt;Solución definitiva&lt;/strong&gt;: Usa HTTPS en desarrollo, desactiva Cloudflare para entornos locales, y asegura que las cookies se manejen con &lt;code&gt;SameSite=None; Secure&lt;/code&gt; en producción.&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>javascript</category>
      <category>security</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
