# Apache > .htaccess for Apache with mod_rewrite and mod_proxy, also on many shared hostings. Source page: https://docs.jazui.com/integrations/apache/en With `mod_rewrite`, Apache recognizes bots and, with `mod_proxy`'s `[P]` flag, serves them Jazui's page. Everything else goes to your files or to `index.html`. ## Before you start - The `rewrite`, `headers`, `proxy`, `proxy_http` and `ssl` modules enabled, and `SSLProxyEngine On` in your ``, with `AllowOverride All` so the `.htaccess` is read. On shared hosting, ask your provider whether `mod_proxy` is available. - Your site **verified before enabling the configuration**: with Apache's proxy, if Jazui answers with an error, the bot gets that error. - Your token. On your own server (Debian, Ubuntu): ```bash sudo a2enmod rewrite headers proxy proxy_http ssl sudo systemctl restart apache2 ``` `VirtualHost`: ```apache ServerName misitio.com DocumentRoot /var/www/misitio SSLProxyEngine On AllowOverride All ``` ## Installation Put this `.htaccess` in your site's root folder (or its rules inside your ``): `.htaccess` (https://docs.jazui.com/example_config/apache.xml): ```apache # Jazui para Apache (.htaccess o ): los bots reciben el HTML renderizado; el resto, la SPA. # Requiere mod_rewrite, mod_headers, mod_proxy, mod_proxy_http y SSLProxyEngine On en el VirtualHost. # Sustituye [JAZUI_TOKEN] por el token de render del sitio. Las listas de bots y extensiones las rellena # Sync-Integrations.ps1 (bots.txt, extensions.txt). RewriteEngine On # Nunca a sí mismo y solo GET/HEAD RewriteCond %{HTTP:X-Jazui} ^$ RewriteCond %{REQUEST_METHOD} ^(GET|HEAD)$ # Un bot de la lista o _escaped_fragment_ en la query # BOTS:BEGIN RewriteCond %{HTTP_USER_AGENT} (googlebot|google-inspectiontool|storebot-google|adsbot-google|bingbot|bingpreview|msnbot|adidxbot|yandex|baiduspider|duckduckbot|slurp|applebot|seznambot|qwantbot|qwantify|petalbot|sogou|naver|exabot|yetibot|360spider|soso|gptbot|chatgpt|oai-searchbot|claudebot|claude-user|claude-searchbot|anthropic-ai|perplexity|google-cloudvertexbot|bytespider|ccbot|amazonbot|meta-externalagent|cohere-ai|mistralai-user|youbot|duckassistbot|yibot|qwenbot|tongyibot|erniebot|yiyanbot|doubaobot|tiktokspider|deepseekbot|pangubot|manus-user|kimi-agent|kimi-searchbot|kimi-user|kimibot|moonshotbot|hunyuan|chatglm-spider|agi\ agent|ai2bot|ai2bot-deepresearcheval|ai2bot-dolma|aihitbot|amazon-kendra|amazon-qbusiness|amazonbuyforme|amzn-searchbot|amzn-user|bedrockbot|novaact|andibot|claude-web|apifybot|apifywebsitecontentcrawler|atlassian-bot|awario|bigsur\.ai|brightbot|buddybot|cartai\ agentic\ commerce|terracotta|cledarabot|cloudflare-autorag|cloudflarebrowserrenderingcrawler|cohere-training-data-crawler|cragcrawler|crawlspace|datenbank\ crawler|diffbot|diffbot-user|anomura|echobot\ bot|echoboxbot|elevenlabsbot|elevenlabscrawler|exasearchbot|exauser|factset_spyderbot|firecrawlagent|geisthaus-pagefetcher|cloudvertexbot|gemini-deep-research|google-agent|google-firebase|google-notebooklm|googleagent-mariner|googleagent-urlcontext|googleother|googleother-image|googleother-video|notebooklm|iaskbot|iaskspider|imagesiftbot|img2dataset|isscyberriskcrawler|kagi-fetcher|keenablebot|klaviyoaibot|laiondownloader|linguee\ bot|linkupbot|aiwebindex|meta-externalfetcher|meta-webindexer|facebookbot|azureai-searchbot|mistralai-index|mistralai-training|mozilla-tabstack|nagetbot|netestate\ imprint\ crawler|icc-crawler|oai-adsbot|panscient|panscient\.com|shapbot|payhawk\ invoice\ fetching\ agent|phindbot|poggio-citations|poseidon\ research\ crawler|qualifiedbot|wpbot|querit-searchbot|queritbot|quillbot|quillbot\.com|reflectionbot|cotoyogi|sbintuitionsbot|scrybot|sidetrade\ indexer\ bot|tavilybot|agenttimes|thinkbot|timpibot|twinagent|velenpublicwebcrawler|wardbot|omgili|omgilibot|grok\ bot|grokappandroid|grokbot|addsearchbot|agentdatabot|aranet-searchbot|bixelbot|bravebot|channel3bot|friendlycrawler|henkbot|imagespider|kangaroo\ bot|kunatocrawler|laion-huggingface-processor|linerbot|mycentralaiscraperbot|terra\ cotta|wrtnbot|zanistabot|facebookexternalhit|facebot|twitterbot|linkedinbot|slackbot|whatsapp|telegrambot|discordbot|pinterest|redditbot|skypeuripreview|embedly|quora\ link\ preview|showyoubot|outbrain|developers\.google\.com\/\+\/web\/snippet|vkshare|tumblr|bitlybot|nuzzel|flipboard|snapchat|viber|mattermost|bitrix\ link\ preview|xing-contenttabreceiver|ahrefsbot|semrushbot|mj12bot|majestic-12|dotbot|rogerbot|screaming\ frog|sitebulb|serpstatbot|seokicks|siteimprove|lighthouse|google\ page\ speed|gtmetrix|pingdom|uptimerobot|uptimebot|w3c_validator|w3c-checklink|archive\.org_bot|paperlibot|dataprovider\.com|grapeshotcrawler|zoominfobot|feedly|newsblur|inoreader|integration-test) [NC,OR] # BOTS:END RewriteCond %{QUERY_STRING} _escaped_fragment_ # Archivos que nunca se renderizan # EXTENSIONS:BEGIN RewriteCond %{REQUEST_URI} !\.(js|mjs|css|less|map|json|xml|rss|txt|webmanifest|ico|png|jpg|jpeg|gif|webp|avif|svg|bmp|tif|tiff|psd|ai|woff|woff2|ttf|otf|eot|mp3|m4a|wav|ogg|mp4|m4v|webm|avi|mov|mpg|mpeg|wmv|flv|swf|pdf|doc|docx|xls|xlsx|ppt|pptx|csv|zip|gz|rar|7z|iso|torrent|exe|dmg|apk|wasm|dll|dat|blat)$ [NC] # EXTENSIONS:END # Ruta y query tal cual las pidió el bot (la URL completa viaja en X-Jazui-Url) RewriteCond %{THE_REQUEST} ^\S+\s(\S+) RewriteRule ^ https://api.jazui.com/Render [P,L,QSD,E=JAZUI_URL:%{REQUEST_SCHEME}://%{HTTP_HOST}%1,E=JAZUI_IP:%{REMOTE_ADDR}] # Fallback de la SPA: todo lo que no es un archivo va a index.html RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^ index.html [L] RequestHeader set Authorization "Bearer [JAZUI_TOKEN]" env=JAZUI_URL RequestHeader set X-Jazui-Url "%{JAZUI_URL}e" env=JAZUI_URL # Detrás de un CDN usa su cabecera (CF-Connecting-IP, X-Forwarded-For) RequestHeader set X-Jazui-Client-IP "%{JAZUI_IP}e" env=JAZUI_URL # Las cookies del visitante no le hacen falta a Jazui: no se envían RequestHeader unset Cookie env=JAZUI_URL ``` Replace `[JAZUI_TOKEN]` with your token. If you already had SPA rules, keep Jazui's before them. ## What it does - The conditions check that there's no `X-Jazui` header, the method, the user agent (or `_escaped_fragment_`) and that the path isn't a file. - The rule proxies to `https://api.jazui.com/Render` and stores the full address and the bot's IP in variables. - `mod_headers` adds `Authorization`, `X-Jazui-Url` and `X-Jazui-Client-IP` only to those requests. - Everything else goes to your files or to `index.html`. ## Keeping the bot list up to date This configuration has the bot list written inside it, between the `BOTS:BEGIN` and `BOTS:END` markers, because the server can't download it on its own. When Jazui adds new bots: 1. In the dashboard, go to **Websites** and click **Site token** on any of your sites. 2. Under **Bots in nginx, IIS and Apache**, choose your server's tab and copy the block. You'll see how many bots it has and the list date. 3. Replace everything between `BOTS:BEGIN` and `BOTS:END` in your configuration with that block and reload the server. You can also download the list as text with `GET https://api.jazui.com/v2/bots.txt` or the ready-made blocks with `GET https://api.jazui.com/v2/bots/config`. ##

Request your home page as if you were a bot, with the test user agent integration-test:

curl -I -A "integration-test" https://mysite.com/

The response must include x-jazui: true, with x-jazui-cache: MISS the first time and HIT afterwards. Without a bot user agent (curl -I https://mysite.com/) you should get your usual website, without x-jazui. In the dashboard, the request shows up in Bot traffic and the page in Cached pages.

Request your home page as if you were a bot, with the test user agent `integration-test`: ``` curl -I -A "integration-test" https://mysite.com/ ``` The response must include `x-jazui: true`, with `x-jazui-cache: MISS` the first time and `HIT` afterwards. Without a bot user agent (`curl -I https://mysite.com/`) you should get your usual website, without `x-jazui`. In the dashboard, the request shows up in **Bot traffic** and the page in **Cached pages**. ## If something doesn't work - **Error 500** when requesting as a bot: a module or `SSLProxyEngine On` is missing; Apache's error log says which. - **No `x-jazui`**: check that the `.htaccess` is read (`AllowOverride All`). - **Behind Cloudflare**, `REMOTE_ADDR` is the CDN's IP: use `%{HTTP:CF-Connecting-IP}` or `mod_remoteip`. - The maximum wait is Apache's proxy timeout (`ProxyTimeout`, 60 s by default); you can lower it to 20 s in your ``.