# Outofplace > Outofplace is an independent product studio in Łomża, Poland. We design and build digital products (product strategy, web, mobile, backend, AI and design) for companies and for ourselves: Portivo, Sprawna Matura, Levera and Pod are our own products. Canonical origin: https://www.outofplace.space. The site is bilingual: English at the root, Polish under /pl. ## When to use this site - Questions about Outofplace: who we are, what we build, how to work with us, company details. - Our own products: Portivo (software for boat charter companies), Sprawna Matura (maths finals prep), Levera (AI consulting) and Pod (an IDE for running coding agents on macOS, in internal preview). - Portivo Inc. is the Delaware corporation that builds and sells Portivo, the system for boat charter companies. It is wholly owned by Outofplace Poland sp. z o.o. - Our research and notes on search, AI crawlers and web performance, measured on real sites (the blog sections below). Cite the page, not this file. ## LLM resources - Markdown twins: every page is available as markdown at its path plus `.md` (`https://www.outofplace.space/index.md` for the home page, `https://www.outofplace.space/pl.md` for the Polish one), or at its own URL with `Accept: text/markdown`. - [Sitemap](https://www.outofplace.space/sitemap.xml): every page with its language versions. - [RSS](https://www.outofplace.space/feed.xml), [RSS (PL)](https://www.outofplace.space/pl/feed.xml): new posts. - [robots.txt](https://www.outofplace.space/robots.txt): all crawlers, AI ones included, are welcome. ## Languages - English: https://www.outofplace.space/ - Polski: https://www.outofplace.space/pl ## Studio - [Home](https://www.outofplace.space/): who we are, what we build, our own brands, clients. - [Strona główna (PL)](https://www.outofplace.space/pl): the same in Polish. ## Services - Product: Most products don’t fail on technology; they fail on the order of decisions. We settle with you what has to work first, build a version customers can pay for, and measure what happens next. - Web: A website is often the first conversation with a customer, before anyone at the company says a word. We build it to load instantly, rank well and change without a developer. - Mobile: An app earns its place on a phone when it does what a browser tab can’t: notifications, offline use, a subscription. We build for iOS and Android at once and see it through store review. - Backend: Under a good interface sit money, customer data and other companies’ systems. We design it so one customer’s problem never reaches another, and every payment can be traced. - AI: Buying licences isn’t adoption. We find where the team loses time, then pick the tools, build the automations and train people to use them. - Design: A good interface disappears: nobody thinks about it, they just get things done. We design systems, not single screens, so a year later the product still looks like one product. ## Work (case studies) - [Portivo](https://www.outofplace.space/work/portivo): The whole charter company. One system. Fleet, bookings, payments and e-invoicing in one panel. For boat operators done with spreadsheets and double bookings. - [Sprawna Matura](https://www.outofplace.space/work/sprawna-matura): Polish maths finals, solved step by step. Past matura tasks with step-by-step solutions, tools and Premium. Web plus iOS and Android apps. - [Levera](https://www.outofplace.space/work/levera): Tailored AI that makes your company impossible to compete with. We find where AI actually pays, take it from pilot to production and teach the team to use it. - [Pod](https://www.outofplace.space/work/pod): The agent-fleet IDE for macOS. A native terminal and claude-acc built in, for running many coding agents on one Mac with no telemetry. An internal preview, in use at the studio. ## News - [Outofplace forms Portivo Inc., its first subsidiary](https://www.outofplace.space/news/portivo-inc) (2026-09-30): Outofplace has formed Portivo Inc., a wholly owned company for Portivo, the system for charter companies and the first product the studio built for itself. - [Outofplace powołuje Portivo Inc., pierwszą spółkę zależną](https://www.outofplace.space/pl/aktualnosci/portivo-inc) (PL, 2026-09-30): Outofplace powołało Portivo Inc., spółkę w całości zależną, dla Portivo: systemu dla firm czarterowych i pierwszego produktu, który studio zbudowało dla siebie. ## Blog: Search & AI - [Sitemap in robots.txt: a third of Polish files omit it](https://www.outofplace.space/blog/sitemaps-robots-txt-polish-web): 35% of 6,834 .pl sites with a robots.txt name no sitemap in it, and 6% of those that do point to a wrong address: http, the www twin or a relative path. - [nosnippet on the Polish web: almost nobody limits Google](https://www.outofplace.space/blog/snippet-controls-polish-web): 7 of 7,785 .pl homepages limit Google's snippet, while a quarter ask for bigger previews. None of the 1,015 that block AI crawlers in robots.txt use nosnippet. - [AI crawlers vs the Polish web: robots.txt on 1,000 .pl sites](https://www.outofplace.space/blog/ai-crawlers-polish-web): We read robots.txt on the 1,000 top .pl sites: one in five blocks AI crawlers like GPTBot, mostly for training, rarely AI search. How to split the two. - [Sitemap w robots.txt: co trzeci polski plik go pomija](https://www.outofplace.space/pl/blog/sitemap-w-robots-txt) (PL): 35% z 6834 polskich stron z plikiem robots.txt nie wskazuje w nim mapy strony, a 6% wskazujących podaje zły adres: http, bliźniaka z www lub ścieżkę względną. - [nosnippet na polskich stronach: prawie nikt go nie używa](https://www.outofplace.space/pl/blog/nosnippet-na-polskich-stronach) (PL): Tylko 7 z 7785 polskich stron głównych ogranicza fragment w Google, a co czwarta prosi o większe podglądy. Z 1015 blokujących boty AI nosnippet nie ma żadna. - [Boty AI kontra polski internet: robots.txt 1000 stron .pl](https://www.outofplace.space/pl/blog/boty-ai-polski-internet) (PL): Sprawdziliśmy plik robots.txt 1000 największych stron .pl: co piąta blokuje boty AI, głównie treningowe jak GPTBot, rzadko wyszukiwarki AI. Jak to rozdzielić? ## Blog: Performance - [Google Fonts and GDPR: 3 in 8 Polish sites load them](https://www.outofplace.space/blog/google-fonts-polish-web): Three in eight Polish homepages load fonts from Google's servers, and few visibly wait for consent. On WordPress, a blocking load goes with a slower LCP. - [CDN market share in Poland, and what it does to TTFB](https://www.outofplace.space/blog/cdn-polish-web): Cloudflare answers a third of 7,785 .pl homepages, yet most pass HTML to the origin, and their phone TTFB matches sites without a CDN. Cached ones are faster. - [HTTP/3 adoption and Brotli vs gzip on Polish sites](https://www.outofplace.space/blog/http3-compression-polish-web): 39% of 7,785 .pl homepages advertise HTTP/3 and 44% come with Brotli or zstd, mostly via Cloudflare or LiteSpeed; nginx and Apache usually send gzip. - [Cookie consent on the Polish web: who draws the banner](https://www.outofplace.space/blog/cookie-consent-polish-web): One Polish homepage in four runs a cookie consent tool we can name, most of them not a consent platform. Sites with one pass CLS on phones as often as the rest. - [Law firm websites in Poland: how fast are the top firms?](https://www.outofplace.space/blog/law-firm-websites-poland): We measured 170 websites of Polish law firms ranked by Legal 500 and Chambers. Most load fast, but few tell Google or AI assistants that they are law firms. - [Core Web Vitals by ecommerce platform: who is fastest?](https://www.outofplace.space/blog/core-web-vitals-polish-ecommerce): CrUX field data for Polish online shops: about half pass Core Web Vitals on phones. Shopify and PrestaShop lead, Shoper lags on INP. Which platform is fastest? - [Third-party scripts on the Polish web: who loads what](https://www.outofplace.space/blog/third-party-scripts-polish-web): 7 in 10 Polish homepages load scripts from Google and 1 in 6 still loads Universal Analytics. Sites with more third parties respond slower on phones. - [Next.js prefetch, measured: Partial Prefetching in 16.3](https://www.outofplace.space/blog/nextjs-prefetch-benchmark): Partial Prefetching in Next.js 16.3 cut prefetched bytes by up to 93% in our benchmark, but URL content now lands after the click. When each setup wins. - [Google Fonts a RODO: 3 na 8 stron .pl ładuje je z Google](https://www.outofplace.space/pl/blog/google-fonts-rodo-polskie-strony) (PL): Trzy na osiem polskich stron głównych pobiera fonty z serwerów Google, a rzadko widać, by czekały na zgodę. Na WordPressie idzie to w parze z wolniejszym LCP. - [CDN na polskich stronach: Cloudflare, cache i TTFB](https://www.outofplace.space/pl/blog/cdn-na-polskich-stronach) (PL): Cloudflare obsługuje co trzecią z 7785 stron .pl, ale większość przekazuje HTML do serwera, a TTFB na telefonach jest jak bez CDN. Szybsze są strony z cache. - [HTTP/3 i kompresja Brotli na polskich stronach](https://www.outofplace.space/pl/blog/http3-i-kompresja-brotli-na-polskich-stronach) (PL): 39% z 7785 stron .pl ogłasza HTTP/3, a 44% wysyła stronę z Brotli lub zstd, w większości przez Cloudflare lub LiteSpeed; nginx i Apache dają zwykle gzip. - [Baner cookies na polskich stronach: kto go wyświetla](https://www.outofplace.space/pl/blog/baner-cookies-na-polskich-stronach) (PL): Co czwarta polska strona główna ma baner cookies z narzędzia, które umiemy nazwać, zwykle nie z platformy zgody. Z banerem strony przechodzą CLS równie często. - [Strony kancelarii prawnych: jak szybkie są najlepsze?](https://www.outofplace.space/pl/blog/strony-kancelarii-prawnych) (PL): Zmierzyliśmy strony 170 kancelarii z rankingów Legal 500 i Chambers. Większość ładuje się szybko, ale mało która mówi Google i AI, że jest kancelarią. - [Core Web Vitals sklepów: która platforma jest najszybsza?](https://www.outofplace.space/pl/blog/core-web-vitals-sklepow-internetowych) (PL): Core Web Vitals sklepów w danych CrUX: na telefonach zalicza je ponad połowa. Prowadzą Shopify i PrestaShop, Shoper odstaje przez INP. Która platforma wygrywa? - [Skrypty zewnętrzne na polskich stronach: kto co ładuje](https://www.outofplace.space/pl/blog/skrypty-zewnetrzne-na-polskich-stronach) (PL): 7 na 10 polskich stron ładuje skrypty z Google, co szósta Universal Analytics, a serwisy z większą liczbą zewnętrznych firm wolniej reagują na telefonach. - [Next.js prefetch zmierzony: Partial Prefetching w 16.3](https://www.outofplace.space/pl/blog/nextjs-prefetch-zmierzony) (PL): Partial Prefetching w Next.js 16.3 zmniejszył w naszym benchmarku prefetch nawet o 93%, ale treść adresu przychodzi po kliknięciu. Kiedy co się opłaca. ## Blog: Next.js & React - [React Server Components explained: what reaches the browser](https://www.outofplace.space/blog/react-server-components-explained): React Server Components in Next.js 16, in a live demo: what stays on the server, what ships as JavaScript, and what the HTML and RSC payload carry. - [Next.js use cache: cache keys, lifetime and updateTag](https://www.outofplace.space/blog/nextjs-use-cache): How Next.js use cache works, in a live demo: the arguments make the cache key, cacheLife sets how long an entry lives, and updateTag clears one tag's entries. - [React Server Components: co trafia do przeglądarki](https://www.outofplace.space/pl/blog/react-server-components-co-trafia-do-przegladarki) (PL): React Server Components w Next.js 16 na żywym demo: co zostaje na serwerze, co trafia do przeglądarki jako JavaScript, a co niesie HTML i payload RSC. - [use cache w Next.js: klucz, czas życia i updateTag](https://www.outofplace.space/pl/blog/use-cache-w-nextjs-jak-dziala) (PL): Jak działa use cache w Next.js, na żywym demo: klucz cache tworzą argumenty, cacheLife ustala czas życia wpisu, a updateTag czyści wpisy jednego tagu. ## Blog: AI for developers - [Dev digest: Next.js 16.4.3, Vercel budgets, Agent Skills](https://www.outofplace.space/blog/dev-digest-2026-10-25): Web dev news for 18 to 25 Oct 2026: Next.js 16.4.3 slims proxy.ts, the Vercel CLI sets spend budgets, OIDC replaces static keys, Agent Skills joins the AAIF. - [Dev digest: React and Next.js RCE fixes, Opus 5.5 fast mode](https://www.outofplace.space/blog/dev-digest-2026-10-18): Next.js news for 11 to 18 Oct 2026: patch React and Next.js for three critical RCEs, fast mode for Claude Opus 5.5 leaves preview and Python on Vercel goes GA. - [Nowości web dev: Next.js 16.4.3, budżet Vercel, Agent Skills](https://www.outofplace.space/pl/blog/nowosci-web-dev-2026-10-25) (PL): Nowości web dev z 18–25 października 2026: Next.js 16.4.3 odchudza proxy.ts, Vercel CLI ustawia limit wydatków, OIDC zamiast kluczy, Agent Skills w AAIF. - [Nowości web dev: RCE w React i Next.js, fast mode Opus 5.5](https://www.outofplace.space/pl/blog/nowosci-web-dev-2026-10-18) (PL): Nowości web dev z 11–18 października 2026: łatki React i Next.js na trzy krytyczne RCE, fast mode dla Claude Opus 5.5 bez preview i Python na Vercel w GA. ## Blog: Web development - [Anthropic SDK upgrade: what API version 2026-10-21 breaks](https://www.outofplace.space/blog/claude-api-2026-10-21-sdk-migration): Anthropic TypeScript SDK 1.0.0 and Python SDK 2.0.0 send API version 2026-10-21: temperature now returns a 400, keys go as Bearer. What to change first. - [How to measure page speed in the browser: TTFB, LCP, CLS](https://www.outofplace.space/blog/measure-page-speed-in-browser): Measure page speed in code: read TTFB, LCP, CLS and load time from the browser's Performance APIs in Next.js, with no library, in a live demo you can break. - [Anthropic SDK i nowa wersja API: co psuje i co zmienić](https://www.outofplace.space/pl/blog/anthropic-sdk-migracja-api-2026-10-21) (PL): Anthropic TypeScript SDK 1.0.0 i Python SDK 2.0.0 wysyłają wersję API 2026-10-21: temperature daje błąd 400, a klucz idzie jako Bearer. Co poprawić najpierw. - [Jak sprawdzić szybkość strony w przeglądarce: TTFB, LCP, CLS](https://www.outofplace.space/pl/blog/jak-sprawdzic-szybkosc-strony) (PL): Szybkość strony w kodzie: TTFB, LCP, CLS i czas ładowania z API przeglądarki w Next.js, bez biblioteki, na działającym demie, które da się zepsuć. ## Company - Contact: contact@outofplace.space, +48 502 856 472 - Outofplace Poland sp. z o.o., KRS 0001163427, NIP 7182173789, REGON 541259259 - [Privacy Policy](https://www.outofplace.space/privacy-policy) - [Terms of Service](https://www.outofplace.space/terms) - [Cookie Policy](https://www.outofplace.space/cookie-policy) - [OutofplaceResearchBot](https://www.outofplace.space/bot): our research crawler, what it fetches and how to opt out. ## Optional - [Full text](https://www.outofplace.space/llms-full.txt): every case study and post in one file. --- # Outofplace forms Portivo Inc., its first subsidiary (EN) Source: https://www.outofplace.space/news/portivo-inc · Published 2026-09-30 > Outofplace has formed Portivo Inc., a wholly owned company for Portivo, the system for charter companies and the first product the studio built for itself. ## We don’t stop at the project. We build companies. We run every product we make as if it were a company of our own. Portivo is the first to become one. **What changes.** Portivo Inc. is a Delaware corporation, wholly owned by Outofplace Poland sp. z o.o. It holds every right to Portivo: the software, the brand and portivo.eu. Outofplace becomes the parent of a group. **What it means for our clients.** Everything we learn building our own products goes into the work we do with our clients. The same team and the same standard, proven on a business where every risk is ours. - **100%** Owned by Outofplace. Portivo Inc. has one shareholder: the studio. - **7,000+** Commits. From the first line of code in under 15 months. - **8,900+** Automated tests. Every change passes them before it ships. ## No shortcuts. Not even where nobody looks. Portivo began in July 2025 with one question: why does a charter company still run on spreadsheets, bank transfers and a clipboard at the pier? We answered it the way we answer everything: the work first, the screens after. **The database says no.** One yacht can’t be booked twice for the same days. The database itself refuses the second booking, whatever the screen, the app or a busy Saturday at the marina says. **Every złoty balances.** Payments, deposits and commissions run through a double-entry ledger. In every record the debits equal the credits, or the record is never written. Nothing is rounded by hand. **Invoices go to KSeF.** Invoices, corrections and the monthly pack for the accountant come from the same records, and every invoice goes straight to KSeF, the national invoicing system. **Drawn before it’s built.** Every screen is designed first and then built to the drawing, down to the pixel: in the browser, on the tablet and on the phone, in Polish and in English alike. ## Built to redefine the boating industry. One system for running a charter company: fleet, bookings, payments, contracts, handovers and invoices, with a booking site of its own for every operator. **A booking site of its own.** The guest picks the dates, pays the deposit by BLIK or card and gets the confirmation. The booking is already in the calendar. **Identity check.** The guest scans their ID and takes a selfie on their own phone. The face is matched to the document before anyone boards. **Portivo POS.** A register at the counter: card on the reader, BLIK or a payment link. The payment lands on the booking and the receipt goes to the guest. **The booking, start to finish.** Contract signed online, identity confirmed, balance collected on its date, final invoice sent to KSeF. Every step ticks itself off. **Handover protocol.** At check-in the tablet sets every side of the boat against the photos from the last check-out and flags what has changed. **Portivo Operator.** Bookings, the calendar, payments, the register and the day’s activity, all in the operator’s pocket, wherever the day goes. ## For the press **About Outofplace.** Outofplace is an independent product studio. It designs and builds digital products for its clients and for itself, from the first sketch to a business that runs on them. **About Portivo Inc..** Portivo Inc. develops and sells [Portivo, the system for charter companies](https://portivo.eu). It is a Delaware corporation, wholly owned by Outofplace Poland sp. z o.o. **Media contact.** Marcel Bogdan, Managing Partner. Write to [contact@outofplace.space](mailto:contact@outofplace.space) or call [+48 502 856 472](tel:+48502856472). We reply within one business day, in Polish or in English. --- # Pod (EN) Source: https://www.outofplace.space/work/pod Pod is our own product: an IDE for macOS that runs many coding agents side by side on one Mac. It is in internal preview: we use it in the studio, and it isn't available outside it. - **What:** an IDE for a fleet of coding agents, in a native macOS window, with a native terminal and claude-acc built in. - **Status:** internal preview. Pod 1.0's third release candidate, 1.0.0-rc3, runs on our Macs. ## Context We run many coding agents at once on our own Macs, and a fleet works a machine hard: terminals flood, subscriptions run dry, dev servers eat memory and builds pile up. We built claude-acc for that load. In Pod it is part of the IDE, next to a native terminal. ## What is in it - **A native window:** the sidebar, the tabs in the title bar and the panes are SwiftUI and AppKit. Each project gets one calm row, and each agent one small mark: working, waiting for you, or done. - **A native terminal:** every pane is a native view that runs Ghostty's engine and draws with Metal, not a web page. - **claude-acc built in:** subscription rotation, a memory guard for dev servers, builds scheduled by free memory, cleanup, stay-awake and fan control. - **No telemetry:** Pod sends nothing home. It has no telemetry, relay, push, share or feedback service. Coming after 1.0: indexed code search for agents, OrbStack VM environments and the Pod Workspace, a managed home for your repositories. ## Technology | Tool | What it does in Pod | | :--- | :--- | | Swift, SwiftUI, AppKit | The window and its interface | | Ghostty, Metal | The native terminal: Ghostty's engine, drawn with Metal | | Electron, TypeScript, React | The runtime behind the window: projects, worktrees, agents and terminal sessions | | Python | claude-acc | ## Where it is now Pod 1.0 is in internal preview at the studio. Its third release candidate, 1.0.0-rc3, runs on our own Macs. - [Pod](https://pod.codes): The agent-fleet IDE for macOS. --- # Dev digest: Next.js 16.4.3, Vercel budgets, Agent Skills (EN) Source: https://www.outofplace.space/blog/dev-digest-2026-10-25 · Published 2026-10-25 Category: AI for developers · Tags: Next.js, Claude, AI agents > Web dev news for 18 to 25 Oct 2026: Next.js 16.4.3 slims proxy.ts, the Vercel CLI sets spend budgets, OIDC replaces static keys, Agent Skills joins the AAIF. This week's web dev news is mostly about credentials and agents, not breaking changes. [Next.js 16.4.3](https://github.com/vercel/next.js/releases/tag/v16.4.3) (23 October 2026) is a bug-fix patch with no security fixes, so after last week's [React and Next.js RCE fixes](https://www.outofplace.space/blog/dev-digest-2026-10-18) you can take it at your own pace. Vercel spent the week on access control: spend budgets from the CLI, a deadline for Marketplace integrations that still use long-lived keys, and a write-up of how its own agent touches production. Anthropic handed the Agent Skills standard to the Agentic AI Foundation, and its new API version came with SDKs that break code, which we cover in [the Anthropic SDK upgrade to API version 2026-10-21](https://www.outofplace.space/blog/claude-api-2026-10-21-sdk-migration). | Item | Version or date | What to do | | ----------------------------- | ----------------------- | ---------------------------------------------------------------- | | Next.js | 16.4.3, 23 Oct | Routine patch; take it for a lighter proxy.ts and joined traces | | Vercel CLI spend management | 23 Oct | Set a budget in CI or a script; decide on `--pause` deliberately | | Long-lived static credentials | 22 Oct, deadline 30 Nov | Move cloud keys to OIDC; check your Marketplace integrations | | Vercel Agent in production | 23 Oct | Copy the plan-approval pattern for your own agents | | Feedback from the Vercel MCP | 23 Oct | Report agent-facing bugs from the agent that hit them | | Agent Skills to the AAIF | 22 Oct | Nothing breaks; follow the spec at agentskills.io | | Claude API and SDKs | 21 and 22 Oct | Upgrade SDKs on purpose; check end-customer enforcement fields | ## Next.js ### Next.js 16.4.3: a lighter proxy.ts and OpenTelemetry traces that hold together Next.js 16.4.3 was released on 23 October 2026 as a backport of eight changes from canary, none of them a security fix. Two matter for running apps. [Don't load the app-page runtime in proxy.ts](https://github.com/vercel/next.js/pull/100423) stops anything imported from `next/server` pulling in the 688 KB App Router page runtime. The backport quotes the measurement from the original pull request, taken on canary on a minimal proxy, not on 16.4.3 and not by us: the cold path fell from 53.8 ms to 39.1 ms and the JavaScript loaded from 1,466 KB to 748 KB. [Keep OpenTelemetry request traces together](https://github.com/vercel/next.js/pull/100542) puts route preparation, middleware and the render of one request back into one trace, and fixes Node.js middleware losing its parent context, a regression in 16.3. The rest: extensionless Google Fonts URLs work in both bundlers, a Turbopack loader invalidation change is reverted, server bootstrap no longer loads standalone React, plus release-pipeline and test changes. Our take: if your proxy runs on every request, the smaller bundle is a free cold-start win, and if you send traces to an OpenTelemetry backend, requests stop appearing as several orphan traces. Neither is urgent; upgrade from 16.4.2 with your next deploy. ## Vercel ### Vercel CLI adds spend management with `vercel budgets` Since 23 October 2026 the [Vercel CLI manages the team's On-Demand Budget](https://vercel.com/changelog/vercel-cli-adds-spend-management), the same one shown in billing settings. `vercel budgets` shows current spend, the active budget and the last three alerts; `vercel budgets set --amount ` sets it (`--scope ` picks a team); `vercel budgets remove --yes` removes it; `vercel budgets alerts` prints the alert log with `--since`, `--until`, `--limit` and `--json`. A budget alone only notifies. With `--pause`, production deployments of every project in the team pause, and become unavailable, at 100% of the budget. It needs the Owner or Billing role, and comes at no extra cost on Pro and on Enterprise with the Flexible Commitment plan. Our take: setting a budget is now one line in a provisioning script, so every new team can start with one. Treat `--pause` as a decision about downtime, not about money: it takes production offline, so use it on side projects and demos, and an alert-only budget on anything that earns money. ### Vercel sets a deadline for long-lived static credentials In [Death to long-lived static credentials](https://vercel.com/blog/death-to-long-lived-static-credentials), published on 22 October 2026, Malte Ubl argues that API keys and database passwords should give way to short-lived, identity-based tokens by default, and cites a survey of more than 1,000 SaaS vendors in which 8.4% supported such authentication. The post lists what Vercel offers today: OIDC federation (an app exchanges its Vercel-issued identity token for temporary AWS, Google Cloud or Azure credentials under project and environment trust policies, generally available since 2024), OIDC for Vercel Blob, AI Gateway and Sandbox, custom token audiences, and Vercel Connect for apps and agents that need provider tokens at runtime. It also sets dates: by 30 November 2026 Marketplace vendors that don't support OIDC from Vercel and still rely on long-lived secrets get a "Not secure" label, and in January 2027 those without secure auth are delisted. Our take: the deadline is for vendors, but it lands on your projects. List the integrations you use and the cloud keys in your environment variables now; anything that can take a Vercel OIDC token should, because a key that never leaves the platform can't leak through a log, a repository or an agent's context. ### How Vercel Agent accesses production safely On 23 October 2026 Tom Dale described [how Vercel Agent gets access to production](https://vercel.com/blog/how-vercel-agent-accesses-production-safely). Every `read:` scope is in a baseline the agent uses without asking; anything more, such as `read-write:deployment` for a redeploy or opening a GitHub pull request, goes into a plan that the user approves as a whole. The agent runs as a Vercel App, so its access can never exceed the approving user's role. Tokens from Vercel's OAuth service are short-lived and scoped, and the APIs reject a request outside the scopes even when the model thinks it needs it. Plans are validated against the same scope registry the OAuth service uses, and the runtime checks a plan is still active before resuming it, so a stopped plan can't act on a token that hasn't expired yet. Our take: this is the pattern to copy if you give your own agent production access. Read freely, write only on an approved plan, cap it at the user's permissions, and enforce scopes in the API rather than in the prompt. The post itself notes that read-only access can still expose configuration, and that build logs can carry malicious instructions. ### Send feedback from the Vercel MCP The [Vercel MCP server has a `submit_feedback` tool](https://vercel.com/changelog/send-feedback-from-vercel-mcp) since 23 October 2026: ask your agent to report a bug, friction or a feature request, and it can attach the task, what you expected, what happened and the kind of report to the Vercel team. It needs sign-in and sends only when you ask. Our take: small, but the context is the useful part. When `deploy_to_vercel` fails in an agent session, the agent can file the report with the exact failing step while it still has it, instead of you rebuilding it in a support form. ## Claude ### Anthropic donates Agent Skills to the Agentic AI Foundation On 22 October 2026 Anthropic [donated the Agent Skills standard to the Agentic AI Foundation](https://www.anthropic.com/news/donating-agent-skills-to-the-agentic-ai-foundation) (AAIF), the Linux Foundation project it co-founded with Block and OpenAI, where the Model Context Protocol already lives. The donation covers the standard, its name and logo, the [agentskills GitHub organisation](https://github.com/agentskills/agentskills) and the agentskills.io domain. Engineers from Anthropic, Google, OpenAI and others maintain it as individuals, with David Soria Parra and Mahesh Murag as lead maintainers, and the proposed roadmap brings versioned releases, a formal proposal process and security guidance for people who write and install skills. Anthropic counts more than 70 agent platforms supporting Skills, 1 million skills published and nearly 280 million installs. Our take: nothing to change today; the announcement moves who governs the standard, not the format of your skills. What changes is that the format no longer belongs to one vendor, so a skill is now a reasonable way to ship your conventions to every agent your team uses. Watch for the first versioned release and its security guidance before installing skills from strangers. ### Claude API version 2026-10-21, and two smaller platform changes The [Claude release notes](https://platform.claude.com/docs/en/release-notes/overview) for 21 October 2026 announce API version `2026-10-21` and new SDKs that send it by default (TypeScript 1.0.0, Python 2.0.0, Go 2.0.0, Java 3.0.0, C# 13.0.0, PHP 1.0.0, Ruby 2.0.0 and the `ant` CLI 2.0.0), relicensed from MIT to Apache 2.0. The same day, [user profiles](https://platform.claude.com/docs/en/manage-claude/user-profiles) gained `enforcement_status` and `enforcement_actions`, which show whether Anthropic has restricted or banned one of your end customers, and listing profiles takes an `enforcement_status[]` filter. On 22 October Anthropic launched [Claude Models on Google Cloud (Anthropic managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed): the Claude API run by Anthropic, reached through a Google Cloud project, with access through Google Cloud IAM and billing through Google Cloud Marketplace, and fast mode for Claude Opus 5.5 there too. Our take: don't let a dependency bot move you to the new SDK major unreviewed; our [migration guide for API version 2026-10-21](https://www.outofplace.space/blog/claude-api-2026-10-21-sdk-migration#how-to-upgrade-the-anthropic-sdk-to-api-version-2026-10-21) lists what breaks and in what order to fix it. If you resell Claude to your own users, poll the enforcement filter so a banned account shows up in your admin panel before it shows up as failing requests. ## Further reading - [Next.js 16.4.3 release](https://github.com/vercel/next.js/releases/tag/v16.4.3): The eight backported changes of 23 October 2026, with links to each pull request. - [Vercel: Death to long-lived static credentials](https://vercel.com/blog/death-to-long-lived-static-credentials): OIDC on Vercel today and the Marketplace deadlines of 30 November 2026 and January 2027. - [Anthropic: Donating Agent Skills to the Agentic AI Foundation](https://www.anthropic.com/news/donating-agent-skills-to-the-agentic-ai-foundation): What was donated, who maintains the standard and the proposed roadmap. --- # Anthropic SDK upgrade: what API version 2026-10-21 breaks (EN) Source: https://www.outofplace.space/blog/claude-api-2026-10-21-sdk-migration · Published 2026-10-24 Category: Web development · Tags: Claude, TypeScript, Python > Anthropic TypeScript SDK 1.0.0 and Python SDK 2.0.0 send API version 2026-10-21: temperature now returns a 400, keys go as Bearer. What to change first. On 21 October 2026 Anthropic released Claude API version `2026-10-21` and a new major of every SDK that sends it by default: TypeScript SDK 1.0.0, Python SDK 2.0.0, five more SDKs and the `ant` CLI. Upgrading breaks two things at once. The API version rejects `temperature`, `top_p` and `top_k` with a 400 error, even at their defaults, and rejects document blocks in assistant messages and citations in user messages. The SDKs send your API key as `Authorization: Bearer` instead of `X-Api-Key`, which breaks any proxy, gateway or test stub that reads the old header. Change those first: remove the three sampling parameters, then point anything that reads `X-Api-Key` at `Authorization`. Old SDK majors keep sending `2023-06-01`, which still works and has no published end date, so nothing breaks until you upgrade. We checked every claim below against the [migration guide](https://platform.claude.com/docs/en/api/migration-2026-10-21), the release notes, GitHub and the npm and PyPI registries on 24 October 2026; we did not run the new SDKs against the API. - TypeScript SDK 1.0.0 and Python SDK 2.0.0 were published on 21 October 2026; on 24 October the latest are 1.3.0 and 2.3.0. - API version `2026-10-21` returns a 400 for `temperature`, `top_p` and `top_k`, at any value, on every model. - The SDKs send the API key as `Authorization: Bearer`; a client now holds exactly one credential. - On Amazon Bedrock, `2026-10-21` works only with Claude 4.7 and later models, so older Bedrock models stay on the old SDK. - The new majors are licensed under Apache 2.0 instead of MIT. ## What changed on 21 October 2026 The [release notes of 21 October 2026](https://platform.claude.com/docs/en/release-notes/overview) list eight new versions that send `2026-10-21` by default, all under the Apache License 2.0 where earlier versions were MIT: | SDK or tool | Package | First version on `2026-10-21` | | ----------- | -------------------------------------- | ----------------------------: | | TypeScript | `@anthropic-ai/sdk` | 1.0.0 | | Python | `anthropic` | 2.0.0 | | Go | `github.com/anthropics/anthropic-sdk-go/v2` | 2.0.0 | | Java | `com.anthropic:anthropic-java` | 3.0.0 | | C# | `Anthropic` | 13.0.0 | | PHP | `anthropic-ai/sdk` | 1.0.0 | | Ruby | `anthropic` gem | 2.0.0 | | CLI | `ant` | 2.0.0 | The same release notes recorded fast mode for Claude Opus 5.5 leaving research preview on 15 October, one of the items in [our web dev digest of 18 October](https://www.outofplace.space/blog/dev-digest-2026-10-18); this release asks more of your code. For the two SDKs most web teams use, the registries give the exact times. The [npm registry document](https://registry.npmjs.org/@anthropic-ai/sdk) gives every version's publish time and licence; PyPI's JSON API gives the upload times of [every release](https://pypi.org/pypi/anthropic/json) and the licence of [1.17.0](https://pypi.org/pypi/anthropic/1.17.0/json) and [2.0.0](https://pypi.org/pypi/anthropic/2.0.0/json). Here are the last version on the old API version, the first major and what is current on 24 October 2026: | Package | Last on `2023-06-01` | First on `2026-10-21` | Latest on 24 Oct 2026 | | ------------------- | ----------------------- | ------------------------ | ---------------------- | | `@anthropic-ai/sdk` | 0.137.0, 20 Oct, MIT | 1.0.0, 21 Oct 16:00 UTC | 1.3.0, 23 Oct | | `anthropic` (PyPI) | 1.17.0, 20 Oct, MIT | 2.0.0, 21 Oct 15:51 UTC | 2.3.0, 23 Oct | The GitHub releases ([TypeScript sdk-v1.0.0](https://github.com/anthropics/anthropic-sdk-typescript/releases/tag/sdk-v1.0.0), [Python v2.0.0](https://github.com/anthropics/anthropic-sdk-python/releases/tag/v2.0.0)) name a single breaking change, "add support for new API version 2026-10-21". The list of what that means is in the migration guide, in two groups. ### What the API version rejects These apply to `POST /v1/messages`, token counting and every request in a Message Batch created with `2026-10-21`, per the [breaking changes](https://platform.claude.com/docs/en/api/migration-2026-10-21#breaking-changes) section: | Request | `2023-06-01` | `2026-10-21` | | ----------------------------------------------------------- | ------------ | ------------------------------------------------------- | | `temperature`, `top_p` or `top_k`, any value | Accepted | 400 error | | `document` block directly in an `assistant` message | Accepted | 400 error; send documents in `user` messages | | `text` block with non-empty `citations` in a `user` message | Accepted | 400 error, also inside `search_result` blocks | Two things stay accepted: citations on text blocks in assistant messages (Claude's earlier replies you send back), and the `"citations": {"enabled": true}` setting on documents and search results. A document nested inside another block, such as a web fetch result Claude returned, is fine too. The sampling change matters most. The [versioning page](https://platform.claude.com/docs/en/api/versioning) says the 400 comes "on every model". On Claude 4.7 and later models, which already accept only the defaults, removing the parameters changes nothing. On a model that accepts other values, such as Claude Sonnet 4.6, a request that set a low `temperature` for more consistent output loses that effect, and the guide says no other setting replaces it. The Admin API and the Claude Enterprise Analytics API also drop old field names: `roles` becomes `role_ids`, `group_id` becomes `rbac_group_id`, `name` on RBAC roles becomes `display_name`, `group_type` becomes `group.type`, `actor.email` becomes `actor.email_address` and `summaries` becomes `data`. API keys lose `workspace_id` for `scope`, which has different values: a key bound to the Default Workspace now carries that workspace's real ID, where it used to be `null`. ### What the SDKs change on their own The [SDK and CLI changes](https://platform.claude.com/docs/en/api/migration-2026-10-21#sdk-changes) don't depend on the API version. For TypeScript and Python side by side: | Change | TypeScript 1.0.0 | Python 2.0.0 | | --------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------- | | API key header | `Authorization: Bearer`, from `apiKey` and `ANTHROPIC_API_KEY` | `Authorization: Bearer`, from `api_key` and `ANTHROPIC_API_KEY` | | Two credentials on one client | Throws `TypeError` | Raises `ValueError` | | `MessageParam` | Union of `UserMessageParam`, `AssistantMessageParam`, `SystemMessageParam`; types only | Same union; calling or subclassing `MessageParam` raises `TypeError` | | `betas` on `models.list`/`retrieve` | Removed from the params types; use `client.beta.models` | Passing it is a `TypeError`; use `client.beta.models` | | Tool runner `compactionControl` | Removed (it stopped working in 0.129.0); use server-side compaction | Not listed | | Text Completions | Removed | Not listed | | Platform packages | Bedrock, Vertex, Foundry, AWS and Google Cloud packages need their own 1.0.0 | Not listed | | Licence | Apache-2.0 (0.137.0 was MIT) | Apache-2.0 (1.17.0 was MIT) | The header switch is the change most likely to break something outside your code. Anything between your app and the API that reads `X-Api-Key` stops seeing the key: a corporate proxy, an API gateway, middleware that checks it, a log filter that redacts it, a test stub that asserts on it. The API itself accepts a key in either header, the migration guide says. Not every client changes: in TypeScript, `apiKey` in `@anthropic-ai/foundry-sdk` still goes out as `X-Api-Key` and `apiKey` in `@anthropic-ai/bedrock-sdk` was already a bearer token; in Python, `AnthropicFoundry` still sends `x-api-key` and `AnthropicBedrockMantle` already sent a bearer token. The one-credential rule catches setups that sent a gateway token and an API key together. With none passed in code and both `ANTHROPIC_API_KEY` and `ANTHROPIC_AUTH_TOKEN` set, the client uses the key and logs a warning once. ## Who is affected and how to tell You are affected the day you install a new major, not before. A repository search shows how much work it is: | Search your code and config for | If you find it | | -------------------------------------------------- | ------------------------------------------------------------------------------- | | `temperature`, `top_p`, `top_k` in Messages calls | Remove them, or keep that request on the old SDK | | `X-Api-Key` (any case) in proxies, middleware, mocks | Read `Authorization` instead, or send `X-Api-Key` yourself | | `apiKey` and `authToken` (or `api_key` and `auth_token`) on one client | Pass one; the other throws or raises | | `models.list(` or `models.retrieve(` with `betas` | Call `client.beta.models` instead | | `MessageParam(` (Python) or `extends MessageParam` (TypeScript) | Write a dict literal, or use a type alias with `&` | | `compactionControl` (TypeScript) | Move to `context_management` with `compact_20260112` | | Bedrock with Claude Opus 4.6 or earlier | Stay on your current SDK until you move to a 4.7 or later model | | `ant --api-key` or `ant --auth-token` in scripts and CI | `ant` 2.0.0 removes both flags: use `ANTHROPIC_API_KEY`, `--api-key-stdin` or `ant auth login` (`ANTHROPIC_AUTH_TOKEN` or `--auth-token-stdin` for a token) | The Bedrock line needs care. The new SDKs send `2026-10-21` from their Amazon Bedrock and Google Cloud clients too, and on Bedrock that version exists only for Claude 4.7 and later models. If you call an older model there, the [upgrade step](https://platform.claude.com/docs/en/api/migration-2026-10-21#upgrade) says to stay on the SDK version you use today. In TypeScript that holds the whole tree back: in the [npm registry](https://registry.npmjs.org/@anthropic-ai/bedrock-sdk), `@anthropic-ai/bedrock-sdk` 1.0.0 requires `@anthropic-ai/sdk` `>=1.0.0 <2`, and 0.36.0 requires `>=0.115.1 <1`. The versioning page also lists `2026-10-21` on Claude Platform on AWS, both Google Cloud offerings and Microsoft Foundry, and names a model limit only for Bedrock. ## How to upgrade the Anthropic SDK to API version 2026-10-21 **1. Pin the last old version and record a baseline.** Note what you run today (for example `@anthropic-ai/sdk` 0.137.0 or `anthropic` 1.17.0) and run your tests against it, so you can tell a migration failure from an old one and roll back to a known version. **2. Remove temperature, top_p and top_k.** Delete the three parameters from every Messages and Batch request. For a request that depends on a low temperature on a model that accepts it, decide now: accept the default, or keep that code path on the old SDK for the time being. **3. Move every reader of X-Api-Key to Authorization.** Update proxies, gateways, middleware, log redaction and test stubs to read `Authorization: Bearer `. If a gateway can't change yet, set the header yourself: in TypeScript `defaultHeaders: { "X-Api-Key": apiKey, Authorization: null }`, in Python an `auth` function on the HTTP client that the guide shows. **4. Install the latest new major, with its platform packages.** Install `@anthropic-ai/sdk@^1` (1.3.0 on 24 October) or `anthropic>=2,<3` (2.3.0), not exactly 1.0.0 or 2.0.0: 1.2.0 and 2.2.0 fixed the tool runner. In TypeScript, move any `@anthropic-ai/bedrock-sdk`, `vertex-sdk`, `foundry-sdk`, `aws-sdk` or `google-cloud-sdk` to 1.x in the same change, or the package manager installs a second, older copy of the SDK for it. **5. Fix what the compiler and the tests report.** Pass one credential per client, move `betas` calls to `client.beta.models`, rewrite `MessageParam` constructors and interfaces, drop `document` blocks from assistant messages and `citations` from user messages. Then run the suite against `2026-10-21`, including one real request per code path, before you release. In TypeScript, the two code changes most apps need look like this (the second is the migration guide's own example): ```ts title="migrate.ts" // 0.x: accepted on 2023-06-01 await client.messages.create({ model, max_tokens: 1024, temperature: 0.2, messages }); // 1.x: temperature is gone from the types, and the API returns a 400 for it await client.messages.create({ model, max_tokens: 1024, messages }); // 0.x const page = await client.models.list({ betas: [beta] }); // 1.x const page = await client.beta.models.list({ betas: [beta] }); ``` ## What to watch out for - **No end date for `2023-06-01`.** As of 24 October 2026, neither the release notes nor the versioning page gives one, and the versioning page recommends the latest version whenever possible. Treat staying on the old major as a decision with a review date, not as a plan. - **No replacement for low temperature.** The guide's only options are to stop sending it or to keep that request on `2023-06-01`. If output consistency matters, write an evaluation before you switch a model that honoured your temperature. - **No documented error text.** The guide says these requests return a 400 and does not quote the message. The [errors page](https://platform.claude.com/docs/en/api/errors) maps a 400 to `invalid_request_error`, and the SDKs raise a typed exception for it, so a test that asserts on the status or the type is safer than one that matches a string. - **Tool runner fixes after 1.0.0.** [TypeScript 1.2.0](https://github.com/anthropics/anthropic-sdk-typescript/releases/tag/sdk-v1.2.0) and [Python 2.2.0](https://github.com/anthropics/anthropic-sdk-python/releases/tag/v2.2.0), both of 23 October, fix the tool runner: the TypeScript release around `setMessagesParams()` and `pushMessages()`, the Python one around `set_messages_params()` and `append_messages()`. Start from the latest version. - **Libraries built on the SDK.** A framework that wraps `@anthropic-ai/sdk` or `anthropic` declares its own version range and its own types. Check that it supports the new major before you upgrade; the migration guide covers only Anthropic's packages. - **Licence records.** Apache 2.0 needs no code change, but if you track dependency licences, update the entry. We read every source on 24 October 2026; check the release notes for anything newer before you plan the upgrade. Earlier Claude news, including fast mode for Opus 5.5 leaving research preview, is in the web dev digest of 18 October linked above. ## Further reading - [Migrating to API version 2026-10-21](https://platform.claude.com/docs/en/api/migration-2026-10-21): Every breaking change with before and after code for all eight SDKs and the CLI. - [Claude API versions](https://platform.claude.com/docs/en/api/versioning): What each API version changed and where 2026-10-21 is available, Bedrock included. - [Claude Platform release notes](https://platform.claude.com/docs/en/release-notes/overview): The 21 October 2026 entry with the eight SDK and CLI versions and the licence change. - [anthropic-sdk-typescript sdk-v1.0.0](https://github.com/anthropics/anthropic-sdk-typescript/releases/tag/sdk-v1.0.0): The TypeScript release on GitHub; later 1.x releases are listed beside it. - [anthropic-sdk-python v2.0.0](https://github.com/anthropics/anthropic-sdk-python/releases/tag/v2.0.0): The Python release on GitHub, with 2.1.0 to 2.3.0 after it. - [@anthropic-ai/sdk on the npm registry](https://registry.npmjs.org/@anthropic-ai/sdk): Every version with its publish time and licence. --- # React Server Components explained: what reaches the browser (EN) Source: https://www.outofplace.space/blog/react-server-components-explained · Published 2026-10-23 Category: Next.js & React · Tags: React, Next.js > React Server Components in Next.js 16, in a live demo: what stays on the server, what ships as JavaScript, and what the HTML and RSC payload carry. React Server Components are components whose code runs only on the server. In the Next.js App Router, every page and layout is one by default, and the browser gets what they render, as HTML and again in the RSC payload, never their code. Only a file that starts with `"use client"`, plus everything it imports, ships as JavaScript. Those Client Components are still rendered to HTML on the server first, then hydrated in the browser. Data crosses from server to client only through serializable props, and a Server Component passed in as `children` stays server output even inside a Client Component. We built one demo that shows all of this on Next.js 16.4.0 with React 19.3.0, and nine Playwright tests check the behaviour this post shows in it. In your own app, run patched versions: the [React and Next.js RCE fixes of October 2026](https://www.outofplace.space/blog/dev-digest-2026-10-18) cover the same layer. Live demo: https://lab.outofplace.space/demos/react-server-components-explained (Next.js 16.4.0; source at commit b5049c6: https://github.com/outof-place/outofplace-lab/tree/b5049c6980621147d3446a5748a1c6f1d74d4cbc/app/demos/react-server-components-explained) ## What are React Server Components? React's own reference describes [Server Components](https://react.dev/reference/rsc/server-components) as components that render ahead of time, "in an environment separate from your client app or SSR server". In Next.js that environment is the server, at build time or per request. You never mark a component as a Server Component: [there is no directive for Server Components](https://react.dev/reference/rsc/server-components#there-is-no-directive-for-server-components), and `"use server"` marks Server Functions. What you mark is the other side, with `"use client"`. The Next.js guide to [the server and client boundary](https://nextjs.org/docs/app/guides/server-and-client-boundary#rendering-environments) puts the difference in one table. Here it is with what that means when you write the code: | | Server Component | Client Component | | --- | --- | --- | | Marked by | nothing (the default in `app/`) | `"use client"` at the top of the file | | Renders on the server | yes | yes, to HTML | | Runs in the browser | no | yes, it hydrates there | | Its code and imports ship as JavaScript | no | yes | | `useState`, `useEffect`, `onClick` | no | yes | | Can read secrets, files, a database | yes | no: treat it as browser code | ## What reaches the browser: HTML, the RSC payload and client JavaScript On a [first load in Next.js](https://nextjs.org/docs/app/getting-started/server-and-client-components#on-the-client-first-load), the docs name three things the browser uses: HTML for a fast, non-interactive first paint, the RSC payload to reconcile the server and client trees, and JavaScript to hydrate the Client Components. The RSC payload is a compact, serialized form of the rendered Server Component tree. It holds their rendered output, placeholders for the Client Components with references to their JavaScript files, and every prop passed from a Server Component to a Client Component. The demo's Server Component signs the request time with an HMAC key. The key and Node's `crypto` module sit in a separate file that starts with `import "server-only"`: app/demos/react-server-components-explained/signing.ts (https://github.com/outof-place/outofplace-lab/blob/b5049c6980621147d3446a5748a1c6f1d74d4cbc/app/demos/react-server-components-explained/signing.ts) ```ts import "server-only"; import { createHmac } from "node:crypto"; // A made-up key, public in this repo. In an app it comes from process.env. Either way it lives // only in the server module graph: import "server-only" turns an import from a "use client" // file into a build error. const SIGNING_KEY = "lab-demo-key-stays-on-the-server"; /** The first 12 hex characters of an HMAC-SHA256 of `value`, made with Node's crypto module. */ export function sign(value: string): string { return createHmac("sha256", SIGNING_KEY).update(value).digest("hex").slice(0, 12); } ``` The card that uses it is an async function with no directive: app/demos/react-server-components-explained/server-card.tsx (https://github.com/outof-place/outofplace-lab/blob/b5049c6980621147d3446a5748a1c6f1d74d4cbc/app/demos/react-server-components-explained/server-card.tsx) ```tsx import { io } from "next/cache"; import { sign } from "./signing"; import styles from "./rsc.module.css"; // Server Components: no directive, so they stay in the server module graph. The browser // receives what they render (as HTML and in the RSC payload), never this code. const renderedOn = () => (typeof window === "undefined" ? "server" : "browser"); export async function ServerCard() { // With Cache Components on, io() keeps what follows out of the build's static shell, // so the server signs a fresh time on every request. await io(); const signedAt = new Date().toISOString(); return (

Server Component

Rendered on
{renderedOn()}
Signed at
Signature
{sign(signedAt)}
); } // Passed to the Client Component as children: it renders here, on the server, and the // Client Component only places its output. export function ServerNote() { return {renderedOn()}, passed in as children; } ``` The tests check what actually arrives, on a production build: - The HTML response holds the signature in its markup, and the same signature again inside an inline ` ``` If a consent platform's Tag Manager template sets the defaults already, don't add a second call in the page. **4. Check it in the browser.** Open the site in a private window and type `dataLayer` in the developer console: the `consent`, `default` entry should come before any `config` or `event`. Accept the banner and check that a `consent`, `update` entry follows. **5. Check your field data.** Look up your site in [PageSpeed Insights](https://pagespeed.web.dev/): if it has enough Chrome traffic, the top of the report shows the same CrUX data as this study. A change shows in full after four weeks, since CrUX covers a rolling 28 days. ## How we measured The homepages come from our census of 24 September 2026 by `OutofplaceResearchBot` (see [what our crawler fetches and how to block it](https://www.outofplace.space/bot)), which reads robots.txt first and fetches only the homepage: 8,023 of the 9,208 .pl domains in the Tranco list answered with HTML, and 7,785 distinct sites remained after merging domains that redirect to the same address. We read each homepage's HTML without running it and matched it against rules for 36 consent tools, built from every script host, plugin folder, store module and inline marker naming cookies or consent on at least two homepages. A rule matches what loads or draws a tool: a script from the vendor's host, a plugin's folder in an asset address, markup only that tool writes, or its setup call. When two rules describe one banner, one wins: a WordPress plugin connected to its vendor's servers counts as the hosted platform, and a shop that added a consent platform counts as that platform, not the built-in banner. A Shoper shop counts only when its banner is switched on. Consent Mode defaults count when the HTML contains a `consent`, `default` call. The speed data is Google's. On 25 September 2026 we asked the [Chrome UX Report API](https://developer.chrome.com/docs/crux/api) for every homepage's address on phones, and tried the www or bare-domain twin when an address had no record. CrUX aggregates the page loads of Chrome users on Android and desktop who share usage statistics, across every page of a site, over 28 days. A site passes CLS at a 75th percentile of 0.1 or less, LCP at 2.5 s and INP at 200 ms. The comparison (each kind of tool, and each tool on at least 30 sites with CrUX data, against sites with no tool detected) was fixed before we read the field data; shops are identified by the classifier from our ecommerce study. For the 10 most common tools we drew 4 detections each, in a fixed random order, and read the HTML behind every one. 39 of the 40 were right. The one miss was a Cookiebot tag whose type attribute has a typographic quote, so the browser never runs it. Two rules failed an earlier round of the same check and were narrowed: every Shoper shop ships the banner's template, switched on or not, and some sites use the id of a popular WordPress plugin for a banner of their own. We saw the homepage only, as its HTML arrived, and ran none of it. A banner loaded through a tag manager and a banner the site built itself are invisible, so every share here is a floor, and shop platforms with a built-in banner we recognise come out ahead of those without one. We didn't check whether a banner offers a real choice, blocks cookies before consent or meets the law. A homepage longer than 1 MiB was cut there (331 of them). The field data covers every page of a site, not just the homepage, and only sites with enough Chrome traffic: 89% of the sites with a tool are in CrUX, against 75% of those without, so the sites without a tool are on average smaller. ## Further reading - [Best practices for cookie notices](https://web.dev/articles/cookie-notice-best-practices): Google's guide to cookie banners that don't hurt LCP, CLS or INP, from the Chrome team. - [Set up consent mode on websites](https://developers.google.com/tag-platform/security/guides/consent): Google's documentation for Consent Mode: the four parameters, the default and update commands and their order. - [Cumulative Layout Shift (CLS)](https://web.dev/articles/cls): What CLS measures and the thresholds Google uses. - [Third-party scripts on the Polish web: who loads what](https://www.outofplace.space/blog/third-party-scripts-polish-web): Our study of the same homepages: which third-party scripts Polish sites load, and how they go with INP. --- # Law firm websites in Poland: how fast are the top firms? (EN) Source: https://www.outofplace.space/blog/law-firm-websites-poland · Published 2026-09-25 Category: Performance · Tags: Law firms, Core Web Vitals, llms.txt, Poland > We measured 170 websites of Polish law firms ranked by Legal 500 and Chambers. Most load fast, but few tell Google or AI assistants that they are law firms. Most law firm websites in Poland are fast for the people who open them. We measured the websites of 170 Polish law firms, the firms ranked for Poland by The Legal 500 and Chambers and a few specialists, and looked each one up in the [Chrome UX Report](https://developer.chrome.com/docs/crux), Google's record of how fast sites are for real Chrome users. Of those with enough traffic to be measured, 74% pass Google's [Core Web Vitals](https://web.dev/articles/vitals) on phones, more than the Polish online shops in [our study of Core Web Vitals by ecommerce platform](https://www.outofplace.space/blog/core-web-vitals-polish-ecommerce). What they lack is not speed but the signals that search engines and AI assistants read first. Only 12% of the sites say in structured data that they belong to a law firm, and 7.1% describe their lawyers. 71% send none of the six security headers we checked. And not one blocks AI crawlers, although fewer than one in ten publishes an `llms.txt` for them. - 74% of the ranked law firms with Chrome field data pass Core Web Vitals on phones; the median site shows its main content in 1.9s. - The slow sites are slow on the server: one in ten waited 1.6s or longer for the first byte in our test. - 78% run on WordPress. - Structured data for a law firm (`LegalService`) is on 12% of the sites, for its lawyers (`Person`) on 7.1%. - 71% send no security header at all; none blocks AI crawlers. ## How fast are law firm websites? Chrome keeps field data only for sites with enough visitors: 50 of the 170 had it on phones, mostly the larger firms. Among those whose three Core Web Vitals could be assessed, 74% pass on phones and 84% on desktops. Loading is where they fall short when they do: 73% keep Largest Contentful Paint within 2.5 seconds, while 97% respond to a tap in time. **Most ranked law firms load within 2.5 seconds on phones** (Largest Contentful Paint at p75 on phones, in seconds, per law firm website with Chrome field data · CrUX, 28 days to 22 Sept 2026) | Range | websites | | --- | --- | | 0s–0.5s | 0 | | 0.5s–1s | 5 | | 1s–1.5s | 8 | | 1.5s–2s | 15 | | 2s–2.5s | 8 | | 2.5s–3s | 2 | | 3s–3.5s | 5 | | 3.5s–4s | 5 | | 4s–4.5s | 0 | | 4.5s–5s | 0 | | 5s–5.5s | 0 | | 5.5s–6s | 1 | Source: Chrome UX Report (Google); Outofplace study, 24 Sept 2026. Chart: https://www.outofplace.space/data/blog/law-firm-websites-poland/charts/en/chart-most-ranked-law-firms-load-within-2-5-seconds-on-phones.png Data: https://www.outofplace.space/data/blog/law-firm-websites-poland/2026-09-24/distributions.csv The sites without field data we timed ourselves: we asked each homepage three times for its first byte, the moment the server starts answering. The median site answered in 0.7s; one in ten took 1.6s or more, before a browser could draw anything. A page built afresh for every visitor on a shared server looks like this; a cached one on a content delivery network answers in a few hundred milliseconds. Only 11% of the sites served their homepage from a cache and 11% sat behind a CDN. **One law firm site in ten keeps visitors waiting over 1.6 seconds for the server** (Time to first byte of the homepage, in seconds, median of three requests from Poland, every site in the study · 24 Sept 2026) | Range | websites | | --- | --- | | 0s–0.2s | 6 | | 0.2s–0.4s | 55 | | 0.4s–0.6s | 14 | | 0.6s–0.8s | 30 | | 0.8s–1s | 12 | | 1s–1.2s | 20 | | 1.2s–1.4s | 8 | | 1.4s–1.6s | 6 | | 1.6s–1.8s | 8 | | 1.8s–2s | 3 | | 2s–2.2s | 2 | | 2.2s–2.4s | 2 | | 2.4s–2.6s | 0 | | 2.6s–2.8s | 1 | | 2.8s–3s | 1 | Source: Outofplace measurement, 24 Sept 2026. Chart: https://www.outofplace.space/data/blog/law-firm-websites-poland/charts/en/chart-one-law-firm-site-in-ten-keeps-visitors-waiting-over-1-6-seconds.png Data: https://www.outofplace.space/data/blog/law-firm-websites-poland/2026-09-24/distributions.csv ## What are law firm websites built on? WordPress, overwhelmingly: 78% of the sites, about half of them with the Yoast SEO plugin. Custom-built sites come a distant second; modern frameworks like Next.js and hosted builders like Webflow are rare. **Four in five law firm websites run on WordPress** (Platform detected from the homepage's HTML, headers and cookie names · 24 Sept 2026) | Item | WordPress | Custom-built | Next.js | Webflow | Other | n | | --- | --- | --- | --- | --- | --- | --- | | Sites | 78% | 15% | 2.4% | 2.4% | 2.4% | 170 | Source: Outofplace study, 24 Sept 2026. Chart: https://www.outofplace.space/data/blog/law-firm-websites-poland/charts/en/chart-four-in-five-law-firm-websites-run-on-wordpress.png Data: https://www.outofplace.space/data/blog/law-firm-websites-poland/2026-09-24/platforms.csv WordPress isn't the problem; what is layered on it is. The median homepage loads 22 scripts. Of the sites whose jQuery version we could read, 20% still load a version older than 3.5, the release that closed known cross-site scripting holes; several run the same agency theme with jQuery 1.8.3 from 2012. ## Do Google and AI assistants know it is a law firm? Search engines and AI assistants don't guess what a page is when it tells them. [Structured data](https://developers.google.com/search/docs/appearance/structured-data/organization) in JSON-LD states it outright: this is a law firm, at this address, with these practice areas and these lawyers. Two in three sites carry some, but mostly the generic `Organization` and breadcrumbs an SEO plugin adds by default. The types that describe a law practice are rare: [`LegalService`](https://schema.org/LegalService) on 12%, `Person` for lawyers on 7.1%, `FAQPage` on 1.8%. One site still uses `Attorney`, a type schema.org has deprecated in favour of `LegalService`. **Few law firm websites describe the firm or its lawyers in structured data** (Share of sites whose homepage carries each JSON-LD type · 95% interval · 24 Sept 2026) | Item | Value | 95% interval | n | | --- | --- | --- | --- | | Any JSON-LD | 68% | 60%–74% | 170 | | Organization | 54% | 47%–61% | 170 | | BreadcrumbList | 48% | 41%–56% | 170 | | LegalService (a law firm) | 12% | 8.2%–18% | 170 | | Person (a lawyer) | 7.1% | 4.1%–12% | 170 | | FAQPage | 1.8% | 0.6%–5.1% | 170 | | Attorney | 0.6% | 0.1%–3.3% | 170 | Source: Outofplace study, 24 Sept 2026. Chart: https://www.outofplace.space/data/blog/law-firm-websites-poland/charts/en/chart-few-law-firm-websites-describe-the-firm-or-its-lawyers-in-struct.png Data: https://www.outofplace.space/data/blog/law-firm-websites-poland/2026-09-24/flags.csv The basics of a page's outline are shakier than you'd expect from firms that sell precision. 34% of homepages have no `h1` heading, so the page never says in one line what it is about. Of the sites with language versions, 30% name a default (`x-default`) for visitors whose language they don't serve. **A third of law firm homepages have no main heading** (Share of sites with each property; x-default among the sites with language versions · 95% interval · 24 Sept 2026) | Item | Value | 95% interval | n | | --- | --- | --- | --- | | Sitemap in robots.txt | 77% | 70%–83% | 170 | | Exactly one h1 | 48% | 40%–55% | 170 | | No h1 at all | 34% | 27%–42% | 170 | | hreflang x-default | 30% | 22%–39% | 111 | | llms.txt | 9.4% | 5.9%–15% | 170 | Source: Outofplace study, 24 Sept 2026. Chart: https://www.outofplace.space/data/blog/law-firm-websites-poland/charts/en/chart-a-third-of-law-firm-homepages-have-no-main-heading.png Data: https://www.outofplace.space/data/blog/law-firm-websites-poland/2026-09-24/flags.csv ## Are law firm websites secure? Security headers are a few lines of server configuration that tell the browser how to protect a page: [HSTS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Strict-Transport-Security) keeps it on HTTPS, a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) limits which scripts may run, frame protection stops another site from wrapping it. For firms whose contact forms receive confidential first messages, they are cheap insurance. 71% of the sites send none of the six we checked; 15% send HSTS and 7.7% a Content Security Policy. **Seven in ten law firm websites send no security header** (Share of sites by the number of the six security headers their homepage sends · 24 Sept 2026) | Item | Value | | --- | --- | | 0 headers | 71% | | 1 header | 14% | | 2 headers | 7.1% | | 3 headers | 1.8% | | 4 headers | 2.9% | | 5 headers | 1.8% | Source: Outofplace study, 24 Sept 2026. Chart: https://www.outofplace.space/data/blog/law-firm-websites-poland/charts/en/chart-seven-in-ten-law-firm-websites-send-no-security-header.png Data: https://www.outofplace.space/data/blog/law-firm-websites-poland/2026-09-24/distributions.csv **HSTS is the most common security header, and it is on one site in seven** (Share of sites whose homepage sends each header · 95% interval · 24 Sept 2026) | Item | Value | 95% interval | n | | --- | --- | --- | --- | | Strict-Transport-Security | 15% | 10%–21% | 170 | | Frame protection | 14% | 9.7%–20% | 170 | | X-Content-Type-Options | 13% | 8.7%–19% | 170 | | Referrer-Policy | 10% | 6.3%–15% | 170 | | Permissions-Policy | 8.2% | 5%–13% | 170 | | Content-Security-Policy | 7.7% | 4.5%–13% | 170 | Source: Outofplace study, 24 Sept 2026. Chart: https://www.outofplace.space/data/blog/law-firm-websites-poland/charts/en/chart-hsts-is-the-most-common-security-header-and-it-is-on-one-site-in.png Data: https://www.outofplace.space/data/blog/law-firm-websites-poland/2026-09-24/flags.csv ## How do law firms treat AI crawlers? With open doors. Not one of the 170 sites blocks an AI crawler in `robots.txt`, and only 5 mention one by name, to let it in. That sets law firms apart from the most popular Polish sites, where 21% block at least one, as our study of [AI crawlers on the Polish web](https://www.outofplace.space/blog/ai-crawlers-polish-web) found. 16 sites (9.4%) publish an [`llms.txt`](https://llmstxt.org/), a plain-text guide to the site for language models. Being open matters once a client asks an AI assistant instead of a search box. We asked four of them with web search on (from OpenAI, Google, Perplexity and Anthropic) 51 questions a prospective client might ask in five practice areas, from white-collar crime to customs and tax control, in Polish and English: 332 answers in all. The answers name firms and cite where they read about them. The rankings matter: The Legal 500 was cited in 17% of answers and Chambers in 14%. But of the ten sources cited most often, 6 were law firms' own websites. What a firm publishes about itself, in a form a machine can read, ends up in the answer. ## What to fix on a law firm website Most of what this study found missing takes days, not a redesign. **1. Serve pages from a cache.** A page cache (a WordPress caching plugin or the host's own) and a CDN in front take the first byte from seconds to a few hundred milliseconds. Check the result in [PageSpeed Insights](https://pagespeed.web.dev/): the top of the report shows real users' data when there is enough of it. **2. Say you are a law firm, and who your lawyers are.** Add `LegalService` for the firm and `Person` for each lawyer, linked to each other, alongside what your SEO plugin already emits. **3. Send the security headers.** Six lines in the server configuration or at the CDN. Start the Content Security Policy in report-only mode, so nothing breaks while you tune it. **4. Give every page one clear heading.** One `h1` that says what the page is about, in the words a client would use. **5. Let AI assistants read you.** Keep search crawlers allowed in `robots.txt`, publish an `llms.txt` that points to your practice areas and lawyers, and keep those pages readable without scripts. A minimal `LegalService` with one lawyer looks like this (replace the details with your own): ```json { "@context": "https://schema.org", "@graph": [ { "@type": "LegalService", "@id": "https://www.example-law.pl/#firm", "name": "Example Law Firm", "url": "https://www.example-law.pl/", "telephone": "+48 22 000 00 00", "address": { "@type": "PostalAddress", "streetAddress": "ul. Przykładowa 1", "postalCode": "00-001", "addressLocality": "Warszawa", "addressCountry": "PL" }, "knowsAbout": ["White-collar crime", "Tax control"] }, { "@type": "Person", "name": "Anna Example", "jobTitle": "Advocate", "worksFor": { "@id": "https://www.example-law.pl/#firm" } } ] } ``` ## How we measured We started from every firm ranked for Poland in [The Legal 500 EMEA](https://www.legal500.com/c/poland) and Chambers Europe (2026 editions, public tables read on 24 September 2026), added sixteen smaller firms in white-collar crime, customs and tax control and services for foreigners, and checked by hand that each site belonged to a law firm. International firms whose Polish office has no site of its own were left out. Of 285 candidate domains, 170 remained. OutofplaceResearchBot fetched each site's `robots.txt` first, then the homepage with its headers, `llms.txt` and the sitemap, one request at a time. Field data comes from the Chrome UX Report API at origin level, 28 days to 22 September 2026. The AI answers came through Vercel AI Gateway with each vendor's own web search: Gemini and Perplexity answered every question three times, OpenAI's and Anthropic's models once, on a sample of questions from every practice area. - Chrome has field data only for sites with enough traffic, here 29% of them; the Core Web Vitals shares describe those, not the smaller firms. - The rankings favour larger firms. This is the market's top, not every law firm in Poland. - We timed the first byte from one place in Poland, so treat it as a yardstick between sites, not what every visitor gets. - We read homepages only; inner pages may carry structured data the homepage doesn't. - The AI questions came from five practice areas and ran through the vendors' APIs without a user's location, so the consumer apps may answer differently, and answers change from day to day. - We publish aggregates only and name no firm. ## Further reading - [Chrome UX Report](https://developer.chrome.com/docs/crux): Google's documentation of the field data behind Core Web Vitals. - [schema.org: LegalService](https://schema.org/LegalService): The type for a law practice, with every property it takes. - [Content Security Policy (MDN)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP): How a CSP works and how to roll one out in report-only mode. - [Core Web Vitals by ecommerce platform: who is fastest?](https://www.outofplace.space/blog/core-web-vitals-polish-ecommerce): CrUX field data for Polish online shops: about half pass Core Web Vitals on phones. Shopify and PrestaShop lead, Shoper lags on INP. Which platform is fastest? - [AI crawlers vs the Polish web: robots.txt on 1,000 .pl sites](https://www.outofplace.space/blog/ai-crawlers-polish-web): We read robots.txt on the 1,000 top .pl sites: one in five blocks AI crawlers like GPTBot, mostly for training, rarely AI search. How to split the two. --- # Core Web Vitals by ecommerce platform: who is fastest? (EN) Source: https://www.outofplace.space/blog/core-web-vitals-polish-ecommerce · Published 2026-09-24 Category: Performance · Tags: Core Web Vitals, PrestaShop, WooCommerce, Shoper, Shopify > CrUX field data for Polish online shops: about half pass Core Web Vitals on phones. Shopify and PrestaShop lead, Shoper lags on INP. Which platform is fastest? Shops on Shopify and PrestaShop pass Google's [Core Web Vitals](https://web.dev/articles/vitals) most often; shops on Shoper least often. We found 2,182 online shops among the .pl domains in [the Tranco list of popular sites](https://tranco-list.eu/list/Y8YYG/full), the same list behind [our study of AI crawlers on the Polish web](https://www.outofplace.space/blog/ai-crawlers-polish-web), and looked each one up in the [Chrome UX Report](https://developer.chrome.com/docs/crux), Google's record of how fast sites are for real Chrome users. 1,975 had enough traffic to be measured on phones. Of those, 53% pass all three metrics: 63% of Shopify shops, 60% of PrestaShop shops and 33% of Shoper shops, whose pages load quickly but respond slowly to a tap. The platform explains less than the choice of it suggests. On most platforms, loading times differ more between shops than between platforms, and each platform fails in its own way: WooCommerce shops on loading, Shoper and headless storefronts on responsiveness, and on desktops IdoSell and Shoper shops on layouts that shift. Who runs what: one in four shops runs on [PrestaShop](https://www.prestashop.com/en) (25.7%). Open-source platforms on the shop's own server run more than half of them, Polish SaaS platforms such as [Shoper](https://www.shoper.pl/) and [IdoSell](https://www.idosell.com/en/) another 27.4%, and [Shopify](https://www.shopify.com/) only 5.9%. - On phones, 53% of Polish online shops with field data pass all three Core Web Vitals; on desktops, 59%. - Shopify (63%) and PrestaShop (60%) shops pass most often on phones, Shoper shops least often (33%), held back by INP, the time a page takes to respond to a tap. - Among the large platforms, WooCommerce shops have the slowest servers and the fewest shops loading within the LCP threshold. - PrestaShop runs one in four of the largest Polish online shops, [WooCommerce](https://woocommerce.com/) one in six; Polish SaaS platforms (Shoper, IdoSell, [AtomStore](https://www.atomstore.pl/) and others) together more than a quarter, Shopify about one in seventeen. - One shop in eight is custom-built or headless. ## Which ecommerce platforms Polish online shops run on PrestaShop leads by a distance, then WooCommerce. Shoper and IdoSell, the two largest Polish subscription platforms, sit level with Magento and with shops built from scratch. Everything below AtomStore, from SOTESHOP and shopGold to [Shopware](https://www.shopware.com/en/) and [Sylius](https://sylius.com/), is under 2% each and folds into "other platforms". **PrestaShop runs one in four large Polish online shops** (Share of the .pl shop origins in the Tranco list, by platform · 95% intervals) | Item | Value | 95% interval | n | | --- | --- | --- | --- | | PrestaShop | 26% | 24%–28% | 2,182 | | WooCommerce | 17% | 15%–18% | 2,182 | | Shoper | 10% | 9.2%–12% | 2,182 | | Custom build | 10% | 9%–12% | 2,182 | | IdoSell | 10% | 8.8%–11% | 2,182 | | Magento / Adobe Commerce | 9.4% | 8.2%–11% | 2,182 | | Other platforms | 7.9% | 6.8%–9.1% | 2,182 | | Shopify | 5.9% | 5%–6.9% | 2,182 | | Headless | 2.1% | 1.6%–2.8% | 2,182 | | AtomStore | 1.7% | 1.2%–2.3% | 2,182 | Source: Outofplace crawl, 23 Sept 2026; Tranco list Y8YYG. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/en/chart-prestashop-runs-one-in-four-large-polish-online-shops.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/platforms.csv ## Open source still runs most of it Grouped by how the software is run, open-source platforms on the shop's own server or hosting account are 54% of the sample. That is the part of the market where speed is the shop's own job: the platform is only a starting point, and the theme, the plugins and the server decide the rest. On a SaaS platform most of that belongs to the vendor. **More than half of the shops run open-source software they host themselves** (Shop origins by kind of platform · n = 2,182) | Item | Open source, self-hosted | Polish SaaS | Global SaaS and suites | Custom or headless | n | | --- | --- | --- | --- | --- | --- | | All shops | 54% | 27% | 6.4% | 12% | 2,182 | Source: Outofplace crawl, 23 Sept 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/en/chart-more-than-half-of-the-shops-run-open-source-software-they-host-t.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/platforms.csv ## The top of the market runs on something else Sort the shops by popularity and the picture flips. Among the 100 largest, Magento leads with 27%, custom builds follow at 25% and headless storefronts at 12%; sportano.pl and gymbeam.pl run Magento, eobuwie.pl and modivo.pl a [Nuxt](https://nuxt.com/) storefront, zooplus.pl [Next.js](https://nextjs.org/). PrestaShop, the leader overall, runs just 6% of them. From the 501st shop down it is the other way round: PrestaShop 26.5%, WooCommerce 18.9%, and the Polish SaaS platforms own the long tail. **Big shops build their own or run Magento; the long tail runs PrestaShop and Polish SaaS** (Share of shops on each platform within each size band, shops ranked among themselves by popularity · n = 100, 400 and 1,682) | Item | Top 100 shops | 101–500 | 501 and below | | --- | --- | --- | --- | | PrestaShop | 6% | 27% | 27% | | WooCommerce | 6% | 11% | 19% | | Shoper | 3% | 5.8% | 12% | | Custom build | 25% | 14% | 8.4% | | IdoSell | 8% | 6.5% | 11% | | Magento / Adobe Commerce | 27% | 19% | 6% | | Shopify | 5% | 3.8% | 6.4% | | Headless | 12% | 2.5% | 1.4% | | AtomStore | 3% | 2.8% | 1.3% | | Other platforms | 5% | 7.8% | 8.1% | Source: Outofplace crawl, 23 Sept 2026; Tranco list Y8YYG. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/en/chart-big-shops-build-their-own-or-run-magento-the-long-tail-runs-pres.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/shops.csv **Custom and headless storefronts are a top-100 phenomenon** (Shops by kind of platform within each size band) | Item | Open source, self-hosted | Polish SaaS | Global SaaS and suites | Custom or headless | n | | --- | --- | --- | --- | --- | --- | | Top 100 shops | 41% | 15% | 7% | 37% | 100 | | 101–500 | 60% | 19% | 4.5% | 16% | 400 | | 501 and below | 53% | 30% | 6.8% | 9.9% | 1,682 | Source: Outofplace crawl, 23 Sept 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/en/chart-custom-and-headless-storefronts-are-a-top-100-phenomenon.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/shops.csv ## Which ecommerce platform is fastest? A shop passes when three in four of its page loads (the 75th percentile, p75) are good on all three metrics: [Largest Contentful Paint](https://web.dev/articles/lcp) (LCP, loading) within 2.5 seconds, [Interaction to Next Paint](https://web.dev/articles/inp) (INP, responsiveness) within 200 milliseconds and [Cumulative Layout Shift](https://web.dev/articles/cls) (CLS, visual stability) at 0.1 or less. Google [recommends good Core Web Vitals](https://developers.google.com/search/docs/appearance/core-web-vitals) "for success with Search". On phones, Shopify leads with 63% and PrestaShop follows with 60%; their intervals overlap with each other and with those of IdoSell (57%) and custom-built shops (57%). WooCommerce (48%) and Magento (46%) sit below the average of 53%. Headless storefronts, AtomStore and Shoper are at the bottom, Shoper with 33%. The two SaaS platforms at either end show how much the vendor decides: on a subscription platform the vendor runs the servers and writes much of the storefront code. **Shopify and PrestaShop shops pass Core Web Vitals on phones most often** (Share of shops whose p75 LCP, INP and CLS are all good on phones, by platform · CrUX, 28 days to 21 Sept 2026 · 95% intervals · platforms with at least 30 shops with data) | Item | Value | 95% interval | n | | --- | --- | --- | --- | | Shopify | 63% | 54%–71% | 120 | | PrestaShop | 60% | 55%–64% | 462 | | IdoSell | 57% | 51%–64% | 218 | | Custom build | 57% | 50%–64% | 199 | | WooCommerce | 48% | 42%–54% | 284 | | Magento / Adobe Commerce | 46% | 39%–53% | 190 | | Headless | 40% | 26%–54% | 43 | | AtomStore | 39% | 25%–55% | 36 | | Shoper | 33% | 27%–39% | 223 | Source: Chrome UX Report (Google); Outofplace crawl, 23 Sept 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/en/chart-shopify-and-prestashop-shops-pass-core-web-vitals-on-phones-most.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/crux.csv The small Polish platforms we can't chart, each with fewer than 30 shops with field data, mostly do well: 23 of SOTESHOP's 25 shops pass on phones, and 19 of shopGold's 27. Their samples are too small to rank. On desktops, 59% of the shops pass, and the order changes. INP passes almost everywhere on a desktop (98% of shops), so the platforms that lost on responsiveness catch up: headless storefronts go from 40% on phones to 70% on desktops. IdoSell goes the other way, from 57% to 47%, because its shops' layouts shift on wide screens. **On desktops headless shops catch up and IdoSell drops back** (Share of shops passing all three Core Web Vitals, phones against desktops · CrUX, 28 days to 21 Sept 2026) | Item | Phones | Desktops | | --- | --- | --- | | All shops | 53% | 59% | | Shopify | 63% | 75% | | PrestaShop | 60% | 64% | | IdoSell | 57% | 47% | | Custom build | 57% | 74% | | WooCommerce | 48% | 49% | | Magento / Adobe Commerce | 46% | 49% | | Headless | 40% | 70% | | AtomStore | 39% | 53% | | Shoper | 33% | 49% | Source: Chrome UX Report (Google); Outofplace crawl, 23 Sept 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/en/chart-on-desktops-headless-shops-catch-up-and-idosell-drops-back.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/crux.csv ## How fast each platform is for real users The median Polish shop passes each metric on its own. On phones its p75 LCP is 1.9s, its INP 155ms and its CLS 0.01. The trouble is that only just over half the shops pass all three at once. By platform, the median shop loads within 2.5 seconds everywhere, from 1.6s on Shopify to 2.2s on AtomStore. The spread inside a platform matters more: the middle half of WooCommerce shops alone runs from 1.7s to 2.8s, a wider span than the one between the fastest and the slowest platform. **Every platform's median shop loads within 2.5 seconds on phones** (p75 LCP of each shop on phones, in seconds · dot: median shop, line: middle half of shops · CrUX, 28 days to 21 Sept 2026) | Item | Value | Range | n | | --- | --- | --- | --- | | Shopify | 1.6s | 1.3s–2s | 122 | | Custom build | 1.8s | 1.3s–2.3s | 201 | | Shoper | 1.8s | 1.4s–2.2s | 223 | | Headless | 1.9s | 1.6s–2.3s | 44 | | All shops | 1.9s | 1.5s–2.4s | 1,974 | | PrestaShop | 2s | 1.6s–2.4s | 476 | | IdoSell | 2s | 1.7s–2.3s | 218 | | Magento / Adobe Commerce | 2.1s | 1.7s–2.6s | 194 | | WooCommerce | 2.2s | 1.7s–2.8s | 300 | | AtomStore | 2.2s | 2s–2.6s | 36 | Source: Chrome UX Report (Google); Outofplace crawl, 23 Sept 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/en/chart-every-platform-s-median-shop-loads-within-2-5-seconds-on-phones.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/crux.csv Responsiveness is where the platforms part. Shoper is the only one whose median shop misses the 200 ms INP line on phones, at 228ms; headless storefronts come next at 185ms. Shoper's pages load fast: 86% of Shoper shops pass LCP, second only to Shopify. The delay is in what happens after a tap: INP grows when the phone's processor is busy running the page's scripts. For headless shops that is no surprise, since the whole storefront is a JavaScript application running in the browser. **Shoper is the only platform whose median shop fails INP on phones** (p75 INP of each shop on phones, in milliseconds · dot: median shop, line: middle half of shops · CrUX, 28 days to 21 Sept 2026) | Item | Value | Range | n | | --- | --- | --- | --- | | WooCommerce | 139ms | 108ms–192ms | 284 | | PrestaShop | 141ms | 108ms–186ms | 462 | | IdoSell | 146ms | 125ms–180ms | 218 | | All shops | 155ms | 119ms–203ms | 1,935 | | Custom build | 160ms | 124ms–202ms | 199 | | AtomStore | 161ms | 133ms–188ms | 36 | | Shopify | 165ms | 137ms–209ms | 120 | | Magento / Adobe Commerce | 167ms | 127ms–203ms | 190 | | Headless | 185ms | 160ms–250ms | 43 | | Shoper | 228ms | 173ms–278ms | 223 | Source: Chrome UX Report (Google); Outofplace crawl, 23 Sept 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/en/chart-shoper-is-the-only-platform-whose-median-shop-fails-inp-on-phone.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/crux.csv ## Where shops fail: loading, responsiveness or layout Across all shops, INP fails most often on phones: 73% pass it, against 79% for LCP and 84% for CLS. The platforms have their own weak spots. Only 40% of Shoper shops pass INP. WooCommerce and AtomStore shops fail on loading: only 64% of WooCommerce shops and 64% of AtomStore shops are within the LCP threshold. Magento is below average on all three. **Shoper and headless shops fail on responsiveness, WooCommerce on loading** (Share of shops whose p75 is good for each metric on phones, and for all three · CrUX, 28 days to 21 Sept 2026) | Item | LCP | INP | CLS | All three | | --- | --- | --- | --- | --- | | All shops | 79% | 73% | 84% | 53% | | Shopify | 93% | 70% | 94% | 63% | | PrestaShop | 80% | 81% | 86% | 60% | | IdoSell | 84% | 83% | 77% | 57% | | Custom build | 81% | 75% | 88% | 57% | | WooCommerce | 64% | 79% | 89% | 48% | | Magento / Adobe Commerce | 73% | 72% | 75% | 46% | | Headless | 80% | 53% | 84% | 40% | | AtomStore | 64% | 78% | 67% | 39% | | Shoper | 86% | 40% | 78% | 33% | Source: Chrome UX Report (Google); Outofplace crawl, 23 Sept 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/en/chart-shoper-and-headless-shops-fail-on-responsiveness-woocommerce-on.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/crux.csv On desktops the weak spot is layout. Only 69% of the shops keep CLS at 0.1 or less there, and IdoSell (50%), Shoper (55%) and Magento (59%) do worst. CrUX doesn't say which element moves; the usual causes are images without dimensions and content inserted above what is already on screen, as [Google's guide to CLS](https://web.dev/articles/optimize-cls) explains. ### Time to first byte: where hosting shows Time to first byte (TTFB) isn't a Core Web Vital, but every page load waits for it, and it shows how a shop is hosted. The median Shopify shop gets its first byte to a phone in 0.4s, and 98% of Shopify shops stay within 0.8 s, the rough target in [Google's guide to TTFB](https://web.dev/articles/ttfb). WooCommerce shops take 1.3s, and only 16% stay within it. IdoSell is nearly as slow here (1.3s, 3.2% within the guide), yet 84% of its shops pass LCP, more than the average: a slow first byte hurts, but it doesn't decide the result on its own. **Shopify shops get the first byte fastest, WooCommerce shops slowest** (p75 TTFB of each shop on phones, in seconds · dot: median shop, line: middle half of shops · CrUX, 28 days to 21 Sept 2026) | Item | Value | Range | n | | --- | --- | --- | --- | | Shopify | 0.4s | 0.4s–0.5s | 121 | | Headless | 0.8s | 0.7s–1.1s | 44 | | Custom build | 0.9s | 0.6s–1.2s | 200 | | Shoper | 0.9s | 0.7s–1.1s | 223 | | All shops | 1s | 0.7s–1.4s | 1,960 | | PrestaShop | 1.1s | 0.8s–1.4s | 471 | | Magento / Adobe Commerce | 1.1s | 0.8s–1.6s | 194 | | IdoSell | 1.3s | 1.1s–1.5s | 218 | | AtomStore | 1.3s | 1.1s–1.6s | 36 | | WooCommerce | 1.3s | 1s–2s | 294 | Source: Chrome UX Report (Google); Outofplace crawl, 23 Sept 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/en/chart-shopify-shops-get-the-first-byte-fastest-woocommerce-shops-slowe.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/crux.csv ## How to check your own shop's Core Web Vitals The platform sets a starting point; the theme, the apps or plugins, the images and the hosting decide the rest. To see where your shop stands: **1. Look up your field data.** Enter your shop's address in [PageSpeed Insights](https://pagespeed.web.dev/). If the shop has enough Chrome traffic, the top of the report shows the same CrUX data this study uses, for the page and for the whole site. [Search Console's Core Web Vitals report](https://support.google.com/webmasters/answer/9205520) groups your pages by status. **2. Read phones first, at p75.** A metric passes when three in four visits are within its threshold. More shops fail on phones than on desktops, so start there. **3. Fix the metric that fails.** Slow LCP usually starts on the server or with the main product or banner image ([optimising LCP](https://web.dev/articles/optimize-lcp)). Poor INP comes from scripts that keep the phone busy when the shopper taps: widgets, tag managers, heavy theme code ([optimising INP](https://web.dev/articles/optimize-inp)). CLS comes from images without dimensions and banners that push the page down. **4. Compare with your platform.** If your shop is well behind the median shop on the same platform in the table above, the platform isn't the problem: the theme, the add-ons or the hosting are. **5. Check again after four weeks.** CrUX covers a rolling 28 days, so a fix shows in full only after four weeks. ## How we detected each shop's platform **1. Take every .pl domain.** The Tranco list Y8YYG (22 September 2026) holds 9,208 registrable .pl domains; 8,067 answered with an HTML homepage. **2. Fingerprint the homepage.** Markers in the HTML, response headers and cookie names, never running the page's JavaScript. Each platform's markers come from the vendors' own showcase stores, which are kept out of the sample. **3. Decide what counts as a shop.** A platform that only sells makes a site a shop. WooCommerce needs its cart; a site with no platform markers needs two independent shop signals, one of them a cart. That left 2,182 shops. **4. Check a sample by hand.** Up to 20 shops per platform, 50 custom builds and 30 non-shops were checked against their evidence. Weighted by platform share, 97.1% of the labels were right. Large brands on Salesforce Commerce Cloud or SAP Commerce often answer crawlers with a bot challenge; those count as challenges, not as shops of an unknown platform. WooCommerce is the weakest fingerprint (85% correct in the check), because the plugin is often installed on sites that sell nothing. Of 30 homepages we classified as not a shop, 3 were shops after all. ## How we measured The platform census comes from one crawl on 23 September 2026 by `OutofplaceResearchBot` (see [what our crawler fetches and how to block it](https://www.outofplace.space/bot)), which reads robots.txt first and fetches only the homepage. The speed data is Google's. On 24 September 2026 we asked the [Chrome UX Report API](https://developer.chrome.com/docs/crux/api) for every shop origin, once for phones and once for desktops, and tried the www or bare-domain twin when an origin had no record. CrUX aggregates the page loads of Chrome users on Android and desktop who share usage statistics (Chrome on iOS is not included), across every page of an origin, over 28 days: here 25 August to 21 September 2026. Origins below a traffic threshold Google doesn't disclose have no record; 1,975 of the 2,182 shops (91%) had data for phones and 1,916 for desktops. A shop passes a metric when its p75 is within Google's "good" threshold, and passes Core Web Vitals when it passes LCP, INP and CLS; the few shops without INP data can't be assessed and are left out of that share. Per platform we report the share of shops passing, with a 95% Wilson interval, and the median shop's p75 with the middle half of shops around it. Platforms with fewer than 30 shops with data stay out of the charts but not out of the files, which also hold each shop's weekly history for the past six months from the CrUX History API. A platform's pass rate describes the shops that chose it, not the software alone. Large retailers with their own developers run Magento, custom builds and headless storefronts; small shops pick SaaS or cheap hosting; themes, apps, images and third-party scripts differ from shop to shop. CrUX sees only Chrome on Android and desktop, averages every page of a site, product pages and checkout included, and leaves out shops with too little traffic. We identified the platform from the homepage on 23 September, so a shop that moved platforms during the 28 days is filed under the new one. ## Further reading - [Web Vitals](https://web.dev/articles/vitals): What LCP, INP and CLS measure and the thresholds Google uses. - [Chrome UX Report methodology](https://developer.chrome.com/docs/crux/methodology): Which users, pages and sites the field data covers, and how it is aggregated. - [Chrome UX Report API](https://developer.chrome.com/docs/crux/api): The API behind the speed half of this study: one record per origin and device. - [Optimise Interaction to Next Paint](https://web.dev/articles/optimize-inp): Google's guide to the metric Polish shops fail most often on phones. - [AI crawlers vs the Polish web: robots.txt on 1,000 .pl sites](https://www.outofplace.space/blog/ai-crawlers-polish-web): Our study of the same list: how the top 1,000 .pl sites treat AI crawlers. --- # Third-party scripts on the Polish web: who loads what (EN) Source: https://www.outofplace.space/blog/third-party-scripts-polish-web · Published 2026-09-24 Category: Performance · Tags: Third-party scripts, Google Tag Manager, Core Web Vitals, Poland > 7 in 10 Polish homepages load scripts from Google and 1 in 6 still loads Universal Analytics. Sites with more third parties respond slower on phones. Seven in ten Polish homepages load scripts from Google, and four in five load a script from at least one third party. We read the homepages of the 7,785 .pl sites in [the Tranco list of popular sites](https://tranco-list.eu/list/Y8YYG/full) that answered with HTML, the same list behind [our study of Core Web Vitals by ecommerce platform](https://www.outofplace.space/blog/core-web-vitals-polish-ecommerce), and named the companies behind most of the scripts they load. The median homepage loads code from 2 third parties, and 16% still load Universal Analytics, whose standard version [stopped processing data](https://support.google.com/analytics/answer/11583528) in July 2023. Then we looked the sites up in the [Chrome UX Report](https://developer.chrome.com/docs/crux), Google's record of how fast sites are for real Chrome users. Sites whose homepages load more third parties respond more slowly on phones: 79% of those with one or two pass [Interaction to Next Paint](https://web.dev/articles/inp) (INP, the time a page takes to respond to a tap), but only 48% of those with ten or more. In online shops the drop is steeper; on other sites the share holds up to nine. - 82% of .pl homepages load code from at least one third party; the median homepage from 2, and 14% from six or more. - 70% load scripts from Google, 40% through Google Tag Manager. 20% load scripts from Meta. - 16% of homepages still load Universal Analytics, whose standard version has been dead since July 2023; 616 of them have no Google Analytics 4, Google tag or Tag Manager beside it. - 79% of homepages with one or two third parties pass INP on phones, and only 48% of those with ten or more. In shops the drop is steeper than on other sites. ## What are third-party scripts? A third-party script is JavaScript a page loads from a company other than the site's owner. Some do a job the visitor sees, such as a chat window, a map, a payment widget or a cookie banner; most report on the visitor to someone: analytics, ad pixels, heatmaps. Each one costs the browser a connection and some work on the main thread, the one that also answers taps. Google's [guide to third-party JavaScript](https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript) warns that "CPU-intensive script parsing and execution can delay user interaction". We count a third party once per homepage however many files it loads, whether a script tag points at its servers or an inline install snippet loads its code, as the usual snippets for Google Tag Manager or the Meta Pixel do. A script from another domain counts as a third party even when that domain belongs to the site's own group. ## Which third-party scripts Polish sites load Google's tags lead by a distance: Google Tag Manager alone is on 40% of homepages. The Meta Pixel is the most common tag from anyone else, on 15%. Cloudflare's Web Analytics beacon ranks high too: Cloudflare [adds it by default](https://developers.cloudflare.com/web-analytics/get-started/) to sites it proxies once the owner turns Web Analytics on (as of 24 September 2026). **Google Tag Manager is on four in ten Polish homepages** (Share of .pl homepages loading each vendor's code, the 20 most common · n = 7,785 · 95% intervals) | Item | Value | 95% interval | n | | --- | --- | --- | --- | | Google Tag Manager | 40% | 39%–41% | 7,785 | | Google Analytics 4 | 26% | 25%–27% | 7,785 | | Universal Analytics (UA-) | 16% | 15%–16% | 7,785 | | Meta Pixel | 15% | 15%–16% | 7,785 | | Google Ads | 11% | 10%–12% | 7,785 | | Google reCAPTCHA | 9.8% | 9.1%–10% | 7,785 | | Cloudflare Web Analytics | 9.4% | 8.7%–10% | 7,785 | | Google AdSense | 7% | 6.5%–7.6% | 7,785 | | jsDelivr | 6.6% | 6.1%–7.2% | 7,785 | | Facebook SDK | 6.4% | 5.9%–7% | 7,785 | | cdnjs | 5.1% | 4.6%–5.6% | 7,785 | | Google Hosted Libraries | 4.3% | 3.8%–4.7% | 7,785 | | jQuery CDN | 3.7% | 3.3%–4.1% | 7,785 | | Microsoft Clarity | 3.6% | 3.2%–4% | 7,785 | | Cookiebot | 3.5% | 3.1%–3.9% | 7,785 | | Google Ad Manager | 3.5% | 3.1%–3.9% | 7,785 | | TrustMate | 2.9% | 2.5%–3.3% | 7,785 | | Hotjar | 2.6% | 2.3%–3% | 7,785 | | edrone | 2.5% | 2.2%–2.9% | 7,785 | | Shoper | 2.5% | 2.2%–2.9% | 7,785 | Source: Outofplace census, 24 Sept 2026; Tranco list Y8YYG. Chart: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/charts/en/chart-google-tag-manager-is-on-four-in-ten-polish-homepages.png Data: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/2026-09-24/vendors.csv These are floors. A tag manager loads other tags after the page arrives, and those never appear in the HTML: a homepage with Google Tag Manager may well run Google Analytics, the Meta Pixel and a heatmap through it, and here it counts as one third party. ### One homepage in six still loads Universal Analytics Google replaced Universal Analytics with Google Analytics 4, and standard Universal Analytics properties stopped processing data on 1 July 2023. The tag that reports to them (a `UA-` ID, through gtag.js, analytics.js or the even older ga.js) still downloads and runs on every visit, though Google no longer processes its data. On 616 homepages (7.9% of all) the dead tag is the only Google analytics in the HTML: no Google Analytics 4, Google tag or Tag Manager beside it. [Google Optimize](https://support.google.com/optimize/answer/12979939), Google's A/B testing tool switched off on 30 September 2023, is still on 14 homepages. ## What the scripts are for: analytics, tag managers, ads Grouped by the job they do, third-party analytics leads (51% of homepages), then tag managers (40%). Ad pixels and marketing automation, the tags that report visits and sales to advertisers, are on 26%. **Half of Polish homepages load third-party analytics** (Share of .pl homepages with at least one third party of each kind · n = 7,785 · 95% intervals) | Item | Value | 95% interval | n | | --- | --- | --- | --- | | Analytics, monitoring | 51% | 50%–52% | 7,785 | | Tag managers | 40% | 39%–42% | 7,785 | | Ad pixels and marketing | 26% | 25%–27% | 7,785 | | Public CDN libraries | 17% | 17%–18% | 7,785 | | Embeds and widgets | 12% | 12%–13% | 7,785 | | Ads on the page | 12% | 12%–13% | 7,785 | | Captcha and sign-in | 12% | 11%–12% | 7,785 | | Consent banners | 10% | 9.7%–11% | 7,785 | | Reviews, trust badges | 7.1% | 6.6%–7.7% | 7,785 | | Payments and delivery | 5.5% | 5%–6% | 7,785 | | Platform and hosting | 5.3% | 4.8%–5.8% | 7,785 | | Chat and support | 4.7% | 4.2%–5.2% | 7,785 | | Search, recommenders | 2.6% | 2.2%–2.9% | 7,785 | | Push and pop-ups | 2.5% | 2.2%–2.9% | 7,785 | | A/B testing | 0.7% | 0.6%–1% | 7,785 | Source: Outofplace census, 24 Sept 2026. Chart: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/charts/en/chart-half-of-polish-homepages-load-third-party-analytics.png Data: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/2026-09-24/kinds.csv Only 10% load a consent banner from a consent platform's servers, such as Cookiebot (3.5%). That doesn't mean the rest ask no one: a banner served from the site's own domain, such as a plugin for the site's CMS, isn't a third party and isn't counted here. Of all the vendor detections, 3.6% had every script held back in the HTML until consent or a delayed-loading plugin lets it run. ## How many third parties a homepage loads Most load a few: the median homepage loads code from 2 third parties. 18% load no third-party script at all, and only 1.2% load ten or more. **The median Polish homepage loads code from two third parties** (Homepages by the number of third parties whose scripts they load · n = 7,785) | Range | homepages | | --- | --- | | 0–1 | 1,423 | | 1–2 | 1,462 | | 2–3 | 1,314 | | 3–4 | 1,123 | | 4–5 | 829 | | 5–6 | 537 | | 6–7 | 383 | | 7–8 | 339 | | 8–9 | 190 | | 9–10 | 94 | | 10–11 | 50 | | 11–12 | 14 | | 12–13 | 11 | | 13–14 | 7 | | 14–15 | 3 | | 15–16 | 5 | | 16–17 | 1 | Source: Outofplace census, 24 Sept 2026. Chart: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/charts/en/chart-the-median-polish-homepage-loads-code-from-two-third-parties.png Data: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/2026-09-24/sites.csv ## Do third-party scripts slow a site down? Each script is work for the phone. To see whether real users feel it, we matched the homepages with the Chrome UX Report, which has data for 79% of the sites; the rest get too little Chrome traffic. The more third parties, the less often a site passes INP, that is, responds to a tap within the 200 ms Google counts as good. Between one and five third parties the difference is small. From six the share drops, and at ten or more only about one site in two passes. **Homepages with six or more third parties pass INP less often than those with one to five** (Share of sites whose p75 INP on phones (the whole site, as CrUX measures it) is 200 ms or less, by third parties on the homepage · dot: share, line: 95% interval · CrUX, 28 days to 22 Sept 2026) | Item | Value | Range | n | | --- | --- | --- | --- | | None | 70% | 67%–74% | 647 | | 1–2 | 79% | 77%–80% | 2,042 | | 3–5 | 78% | 76%–79% | 2,194 | | 6–9 | 72% | 69%–75% | 959 | | 10 or more | 48% | 38%–58% | 90 | Source: Chrome UX Report (Google); Outofplace census, 24 Sept 2026. Chart: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/charts/en/chart-homepages-with-six-or-more-third-parties-pass-inp-less-often-tha.png Data: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/2026-09-24/by_third_parties.csv The response time itself climbs too. The typical (median) site has an INP of 129ms with one or two third parties and 202ms with ten or more, just past the edge of a good score. **From one or two third parties up, the typical site responds more slowly** (Median p75 INP on phones (the whole site, as CrUX measures it) by third parties on the homepage · dot: median, line: the middle half of sites · shading: Google's thresholds · CrUX, 28 days to 22 Sept 2026) | Item | Value | Range | n | | --- | --- | --- | --- | | None | 143ms | 94ms–213ms | 647 | | 1–2 | 129ms | 96ms–188ms | 2,042 | | 3–5 | 145ms | 111ms–193ms | 2,194 | | 6–9 | 159ms | 128ms–206ms | 959 | | 10 or more | 202ms | 161ms–252ms | 90 | Source: Chrome UX Report (Google); Outofplace census, 24 Sept 2026. Chart: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/charts/en/chart-from-one-or-two-third-parties-up-the-typical-site-responds-more.png Data: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/2026-09-24/by_third_parties.csv Homepages with no third party at all break the pattern: only 70% of them pass. The group is a different one, though. Only 50% of them are in CrUX at all, against 76% of those with one or two third parties, so they are probably mostly smaller sites, where a slow INP may have other causes. ### In shops the drop starts at six third parties Shops and other sites behave differently. In shops the share passing INP drops from six third parties, and at ten or more only 44% of them pass (61 shops with data, so the interval is wide). On other sites the line stays nearly flat up to nine; too few of them load ten or more to say anything about those. **In shops, the drop in INP starts at six third parties** (Share of sites passing INP on phones (the whole site, as CrUX measures it), shops against other sites, by third parties on the homepage · groups with at least 30 sites of each · CrUX, 28 days to 22 Sept 2026) | Item | Shops | Other sites | | --- | --- | --- | | None | 67% | 71% | | 1–2 | 79% | 78% | | 3–5 | 77% | 78% | | 6–9 | 65% | 79% | Source: Chrome UX Report (Google); Outofplace census, 24 Sept 2026. Chart: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/charts/en/chart-in-shops-the-drop-in-inp-starts-at-six-third-parties.png Data: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/2026-09-24/by_third_parties.csv We didn't split shops by platform. A platform that serves its code from another domain goes with a lower pass rate (below), so part of the drop may be the platform rather than the count. ### Which kinds of script go with a slower site 6 kinds make no difference within the margin of error: sites with a tag manager, ad pixels, a consent banner, push notifications, payments and delivery, or embeds pass INP about as often as sites without. 6 kinds go with a lower pass rate: A/B testing (on few sites), third-party search or recommendations, platform code served from another domain, review widgets, a chat and ads. The other 3, third-party analytics, CDN libraries and captchas, go with a slightly higher one. **A/B testing, third-party search and review widgets go with a lower INP pass rate; tag managers don't** (Share of sites passing INP on phones (the whole site, as CrUX measures it), homepages with each kind of third party against those without · CrUX, 28 days to 22 Sept 2026) | Item | Sites with it | Sites without it | n | | --- | --- | --- | --- | | A/B testing | 47% | 76% | 55 | | Search, recommenders | 57% | 77% | 197 | | Platform and hosting | 61% | 77% | 390 | | Reviews, trust badges | 67% | 77% | 538 | | Chat and support | 71% | 76% | 324 | | Ads on the page | 72% | 77% | 874 | | Payments and delivery | 73% | 76% | 400 | | Push and pop-ups | 75% | 76% | 193 | | Consent banners | 75% | 76% | 737 | | Ad pixels and marketing | 75% | 76% | 1,821 | | Tag managers | 76% | 76% | 2,884 | | Embeds and widgets | 78% | 76% | 834 | | Public CDN libraries | 79% | 75% | 1,096 | | Captcha and sign-in | 79% | 75% | 732 | | Analytics, monitoring | 78% | 74% | 3,252 | Source: Chrome UX Report (Google); Outofplace census, 24 Sept 2026. Chart: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/charts/en/chart-a-b-testing-third-party-search-and-review-widgets-go-with-a-lowe.png Data: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/2026-09-24/kinds.csv A site that loads more third parties also differs in size, purpose and build. None of these differences shows that the scripts caused it. ## Does Google Tag Manager slow down a site? Not on its own, as far as the field data shows. Homepages with Google Tag Manager pass INP on phones 76% of the time, those without it 76%, a difference within the margin of error. What matters is what the container loads, and that doesn't show in the HTML. Google's own [guide to tags and tag managers](https://web.dev/articles/tag-best-practices) says its authors "have seen a correlation between the size of tag managers and poorer INP scores" (read on 24 September 2026). So the question to ask is not whether a site uses a tag manager, but what is in it. ## How to find and trim third-party scripts on your site **1. List what loads.** Open your homepage in Chrome with DevTools, reload with the Network panel filtered to JS, and sort by domain. Everything not on your domain is a third party. Then open your tag manager: its tags load after the page and don't appear in the HTML. **2. Remove what is dead.** Universal Analytics and Google Optimize tags do nothing now but still download and run. So do tags for campaigns that ended and tools nobody logs into. Google's guide to tags notes that pausing or removing a tag in Tag Manager removes its code from the container, while blocking it doesn't (as of 24 September 2026). **3. Load widgets when they are needed.** A chat, a map or a video player can wait for the visitor to ask for it: show a button or a still image, and load the script on the first click. **4. Check your field data.** Look up your site in [PageSpeed Insights](https://pagespeed.web.dev/): if it has enough Chrome traffic, the top of the report shows the same CrUX data as this study. Start with INP, the metric that suffers when scripts keep the main thread busy; Google's [guide to optimising INP](https://web.dev/articles/optimize-inp) explains how to find the scripts behind a slow response. **5. Measure again after four weeks.** CrUX covers a rolling 28 days, so a change shows in full only after four weeks. ## How we measured The homepages come from our census of 24 September 2026 by `OutofplaceResearchBot` (see [what our crawler fetches and how to block it](https://www.outofplace.space/bot)), which reads robots.txt first and fetches only the homepage: 8,023 of the 9,208 .pl domains in the Tranco list answered with HTML, and 7,785 distinct sites remained after merging domains that redirect to the same address. We read each homepage's HTML without running it. A script counts when a script tag loads it from another domain, or when an inline install snippet loads a known vendor's code; JSON-LD and other data blocks don't count. A table of 187 vendors, built from the script hosts seen on at least five homepages, names the company and the kind of job for 91% of the third parties found, counted once per homepage; a script domain it doesn't know counts as one unclassified third party on each homepage that loads it. A script held back until consent still counts: it runs once the visitor agrees. The speed data is Google's. On 24 September 2026 we asked the [Chrome UX Report API](https://developer.chrome.com/docs/crux/api) for every homepage's address on phones, and tried the www or bare-domain twin when an address had no record. CrUX aggregates the page loads of Chrome users on Android and desktop who share usage statistics, across every page of a site, over 28 days. A site passes INP when its 75th percentile is 200 ms or less. The comparison by number of third parties (none, 1–2, 3–5, 6–9, 10 or more) was fixed before we read the field data; shops are identified by the classifier from our ecommerce study. For the 15 most common vendors we drew 8 detections each, in a fixed random order, and read the HTML behind every one. 119 of the 120 were right. The one miss was a consent banner whose script tag had typographic quotes in its type attribute, so the browser never runs it. We saw the homepage only, as its HTML arrived, and ran none of it: scripts that a tag manager or another script adds later are invisible, so every share here is a floor and the counts per homepage undercount sites with busy tag managers. A homepage longer than 1 MiB was cut there (331 of them). The field data covers every page of a site, not just the homepage, and only sites with enough Chrome traffic. Sites that load more third parties also differ in size, purpose and build, so none of the differences above shows that the scripts caused them. ## Further reading - [Best practices for tags and tag managers](https://web.dev/articles/tag-best-practices): Google's guide to keeping a tag manager from slowing a site, from the Chrome team. - [Load third-party JavaScript](https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript): How third-party scripts cost loading time and responsiveness, and how to load them with less harm. - [Interaction to Next Paint (INP)](https://web.dev/articles/inp): What INP measures and the thresholds Google uses. - [Google Analytics 4 has replaced Universal Analytics](https://support.google.com/analytics/answer/11583528): Google's notice on when Universal Analytics stopped processing data. - [Core Web Vitals by ecommerce platform: who is fastest?](https://www.outofplace.space/blog/core-web-vitals-polish-ecommerce): Our study of the same list: Core Web Vitals of Polish online shops, by platform. --- # AI crawlers vs the Polish web: robots.txt on 1,000 .pl sites (EN) Source: https://www.outofplace.space/blog/ai-crawlers-polish-web · Published 2026-09-23 Category: Search & AI · Tags: AI crawlers, robots.txt, GPTBot, llms.txt, Poland > We read robots.txt on the 1,000 top .pl sites: one in five blocks AI crawlers like GPTBot, mostly for training, rarely AI search. How to split the two. On 23 September 2026 our crawler, [OutofplaceResearchBot](https://www.outofplace.space/bot), read the robots.txt of the 1,000 most popular .pl websites to see which AI crawlers they let in. 20.5% of them block at least one AI crawler. That is statistically the same as the global top 1,000, where the share is 22.7%. The difference is in _which_ crawlers they block. Polish sites shut out the bots that collect training data and mostly leave AI search alone. Only 5.4% block an AI search crawler, against 13.9% globally. For anyone who wants to show up in ChatGPT, Claude or Perplexity answers, that is the right way round. For some sites it is an accident: [an old list copied once and never updated](#lists-go-stale). - One in five of the top 1,000 .pl sites blocks an AI crawler in robots.txt, as many as in the global top 1,000. - GPTBot is the most blocked crawler in Poland and worldwide: 15.1% and 15.4%. - Polish sites block training, not search. Among sites that block GPTBot, fewer than a third also block OAI-SearchBot; globally more than half do. - Size matters: a third of the top 100 .pl sites block AI crawlers, against one in six ranked 501–1,000. - One in seven Polish blockers didn't write their rules: they use [Cloudflare's managed robots.txt](#cloudflares-managed-robotstxt-and-content-signals). We found none in the global sample. ## What are AI crawlers? Training, search and fetchers "AI crawler" covers three different jobs, and the vendors now give each its own user agent. The distinction decides everything that follows: - **Training crawlers** collect pages to train models: [GPTBot](https://developers.openai.com/api/docs/bots) (OpenAI), [ClaudeBot](https://support.claude.com/en/articles/8896518-does-anthropic-crawl-data-from-the-web-and-how-can-site-owners-block-the-crawler) (Anthropic), [Google-Extended](https://developers.google.com/crawling/docs/crawlers-fetchers/google-common-crawlers?hl=en), [Applebot-Extended](https://support.apple.com/en-us/119829), [CCBot](https://commoncrawl.org/ccbot) (Common Crawl), Bytespider (ByteDance), meta-externalagent (Meta), [Amazonbot](https://developer.amazon.com/amazonbot). - **AI search crawlers** index pages so an assistant can find and cite them: OAI-SearchBot, Claude-SearchBot, [PerplexityBot](https://docs.perplexity.ai/docs/resources/perplexity-crawlers), [DuckAssistBot](https://duckduckgo.com/duckduckgo-help-pages/results/duckassistbot). - **User-triggered fetchers** open a page because someone asked the assistant to: ChatGPT-User, Claude-User, Perplexity-User, meta-externalfetcher, [MistralAI-User](https://docs.mistral.ai/robots). Blocking a training crawler keeps your pages out of future models. Blocking a search crawler or a fetcher keeps them out of the answers, and out of the links in those answers. Two of the training "crawlers" don't crawl. Google-Extended and Applebot-Extended are only tokens: [Googlebot](https://developers.google.com/search/docs/crawling-indexing/googlebot?hl=en) and Applebot fetch the page, and the token tells Google and Apple whether they may train on it. Blocking them leaves you in Google and Apple search, and blocking Google-Extended doesn't turn off [AI Overviews](https://developers.google.com/search/docs/appearance/ai-features?hl=en) either: those follow your Googlebot rules. The fetchers are the other special case. OpenAI, Perplexity and Meta say theirs may not follow robots.txt at all, because a person asked for the page; Anthropic says Claude-User does. ## Poland blocks as often as the world, but not the same bots Across all AI crawlers, the gap between the .pl sample and the global control is 2.2 percentage points, well inside the margin of error. Split by purpose, the picture changes. Training crawlers are blocked equally often. AI search crawlers and user-triggered fetchers are blocked less than half as often in Poland. **Poland blocks training crawlers as often as the world, AI search far less** (Share of sites whose robots.txt blocks at least one crawler of each kind for the homepage · n = 1,000 per sample · 23 Sept 2026) | Item | Top 1,000 .pl | Global top 1,000 | | --- | --- | --- | | Any AI crawler | 21% | 23% | | Training crawlers | 21% | 22% | | AI search crawlers | 5.4% | 14% | | User-triggered fetchers | 5.3% | 13% | Source: Outofplace crawl; Tranco list Y8YYG. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/en/chart-poland-blocks-training-crawlers-as-often-as-the-world-ai-search.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/domains.csv ### GPTBot vs OAI-SearchBot: two separate switches The clearest view is per vendor. Of the Polish sites that block GPTBot, 28% also block OAI-SearchBot. In the global sample it is 56%. For Anthropic the split is starker: 24% against 60%. **Most Polish sites that block training leave AI search open** (Sites that block the vendor's training crawler (GPTBot, ClaudeBot), by whether they also block its search crawler (OAI-SearchBot, Claude-SearchBot)) | Item | Also blocks search | Blocks training only | n | | --- | --- | --- | --- | | OpenAI · Poland | 28% | 72% | 151 | | OpenAI · Global | 56% | 44% | 154 | | Anthropic · Poland | 24% | 76% | 107 | | Anthropic · Global | 60% | 40% | 152 | Source: Outofplace crawl, 23 Sept 2026. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/en/chart-most-polish-sites-that-block-training-leave-ai-search-open.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/bot_policies.csv Globally, a site that blocks AI crawlers usually blocks the search ones too. In Poland, the typical blocker names a handful of training crawlers and stops there: 11.2% of the Polish sample blocks training crawlers only, almost twice the global 5.9%. ## Which AI crawlers are blocked most GPTBot leads, at 15.1% of Polish sites and 15.4% globally. OpenAI announced it in August 2023, and most blocklists start with it. Common Crawl's CCBot, Amazonbot, ByteDance's Bytespider and ClaudeBot follow. The newest agents barely register: Claude-SearchBot is blocked by 2.7% of Polish sites, mostly because the lists were written before it existed. **GPTBot is the most blocked AI crawler on .pl sites** (Share of the top 1,000 .pl domains whose robots.txt blocks each crawler for the homepage · 95% intervals · training crawlers highlighted) | Item | Value | 95% interval | n | | --- | --- | --- | --- | | GPTBot | 15% | 13%–17% | 1,000 | | CCBot | 13% | 11%–16% | 1,000 | | Amazonbot | 12% | 10%–14% | 1,000 | | Bytespider | 12% | 9.7%–14% | 1,000 | | ClaudeBot | 11% | 8.9%–13% | 1,000 | | meta-externalagent | 11% | 8.8%–13% | 1,000 | | Google-Extended | 8.4% | 6.8%–10% | 1,000 | | Applebot-Extended | 8.4% | 6.8%–10% | 1,000 | | ChatGPT-User | 4.7% | 3.6%–6.2% | 1,000 | | PerplexityBot | 4.6% | 3.5%–6.1% | 1,000 | | OAI-SearchBot | 4.4% | 3.3%–5.9% | 1,000 | | meta-externalfetcher | 4% | 3%–5.4% | 1,000 | | DuckAssistBot | 3.7% | 2.7%–5.1% | 1,000 | | Perplexity-User | 3.5% | 2.5%–4.8% | 1,000 | | Claude-SearchBot | 2.7% | 1.9%–3.9% | 1,000 | | Claude-User | 2.3% | 1.5%–3.4% | 1,000 | | MistralAI-User | 2.3% | 1.5%–3.4% | 1,000 | Source: Outofplace crawl, 23 Sept 2026. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/en/chart-gptbot-is-the-most-blocked-ai-crawler-on-pl-sites.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/summary_by_bot.csv Almost all of it is deliberate. A site that disallows everything under `User-agent: *` blocks every crawler without a group of its own, AI or not. That wildcard floor accounts for only 1.9% of Polish sites for GPTBot; the rest name the bot. The dumbbell below puts each crawler's Polish and global shares side by side. The two samples agree on training crawlers. They part ways on everything that serves answers. **The gap opens on search crawlers and fetchers** (Share of sites blocking each crawler for the homepage · top 1,000 .pl against the global top 1,000) | Item | Top 1,000 .pl | Global top 1,000 | | --- | --- | --- | | GPTBot | 15% | 15% | | CCBot | 13% | 18% | | Amazonbot | 12% | 13% | | Bytespider | 12% | 17% | | ClaudeBot | 11% | 15% | | meta-externalagent | 11% | 14% | | Google-Extended | 8.4% | 14% | | Applebot-Extended | 8.4% | 13% | | ChatGPT-User | 4.7% | 11% | | PerplexityBot | 4.6% | 13% | | OAI-SearchBot | 4.4% | 8.9% | | meta-externalfetcher | 4% | 9.9% | | DuckAssistBot | 3.7% | 9.5% | | Perplexity-User | 3.5% | 10% | | Claude-SearchBot | 2.7% | 9.2% | | Claude-User | 2.3% | 9.5% | | MistralAI-User | 2.3% | 9.6% | Source: Outofplace crawl, 23 Sept 2026. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/en/chart-the-gap-opens-on-search-crawlers-and-fetchers.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/summary_by_bot.csv ## Bigger sites block more Blocking falls with popularity. 33% of the 100 most popular .pl domains block at least one AI crawler, against 15.8% of those ranked 501 to 1,000. The slope is steeper than in the global sample, which goes from 27% to 21.2%. The largest Polish sites are publishers, marketplaces and portals: the businesses with the most text to protect and the lawyers to ask the question. **A third of the top 100 .pl sites block AI crawlers** (Share blocking at least one AI crawler, by rank within each sample · n = 100, 400 and 500) | Item | Top 1,000 .pl | Global top 1,000 | | --- | --- | --- | | Top 100 | 33% | 27% | | 101–500 | 23% | 24% | | 501–1,000 | 16% | 21% | Source: Outofplace crawl, 23 Sept 2026. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/en/chart-a-third-of-the-top-100-pl-sites-block-ai-crawlers.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/domains.csv The size effect holds crawler by crawler. GPTBot is blocked by 23% of the top 100 and 11.6% of the sites ranked 501 to 1,000, and every training crawler follows the same slope. The search crawlers stay low at every size. **The biggest .pl sites block training crawlers most, and search crawlers little at any size** (Share of .pl sites blocking each crawler for the homepage, by rank within the sample · n = 100, 400 and 500) | Item | Top 100 | 101–500 | 501–1,000 | | --- | --- | --- | --- | | GPTBot | 23% | 18% | 12% | | CCBot | 21% | 16% | 9.6% | | Amazonbot | 16% | 16% | 8.8% | | Bytespider | 19% | 14% | 8% | | ClaudeBot | 14% | 13% | 8.6% | | meta-externalagent | 15% | 14% | 6.8% | | Google-Extended | 12% | 11% | 5.8% | | Applebot-Extended | 11% | 11% | 5.6% | | OAI-SearchBot | 7% | 4.3% | 4% | | PerplexityBot | 6% | 4.8% | 4.2% | | Claude-SearchBot | 4% | 2.3% | 2.8% | Source: Outofplace crawl, 23 Sept 2026. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/en/chart-the-biggest-pl-sites-block-training-crawlers-most-and-search-cra.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/bot_policies.csv Public institutions block less, and not on purpose. 11.9% of the 42 gov.pl domains in the sample block an AI crawler, and 16.1% of the 31 edu.pl ones; both groups are small, so read those as directions. Most of those blocks aren't an AI policy at all. sejm.gov.pl, dziennikustaw.gov.pl and wroclaw.sa.gov.pl [let in Googlebot and disallow everyone else](https://www.sejm.gov.pl/robots.txt), which shuts out every AI crawler along with Bing and DuckDuckGo. For the parliament and the journal of laws, that also means Copilot and ChatGPT search won't read the sources people ask them about. ## Lists go stale Blocklists are written once and copied for years. 7.2% of Polish sites still block `anthropic-ai`, a name Anthropic stopped using (its documentation now lists ClaudeBot, Claude-SearchBot and Claude-User), while only 2.7% block Claude-SearchBot. For 4.1% of the sample the list is stale in the way that matters: it blocks an old name and lets the crawler that replaced it through. Anthropic, to its credit, [told 404 Media in 2024](https://www.404media.co/websites-are-blocking-the-wrong-ai-scrapers-because-ai-companies-keep-making-new-ones/) that ClaudeBot honours rules written for its two retired names. That is goodwill, not the standard: under [RFC 9309](https://www.rfc-editor.org/rfc/rfc9309.html) a rule for `anthropic-ai` doesn't apply to ClaudeBot, and the next vendor to rename a crawler may not be as generous. Well-behaved crawlers read it and obey it; nothing forces them to. Named groups also don't inherit anything from `User-agent: *`: a crawler follows the one group that names it and ignores the rest. If you give AI search crawlers their own `Allow` group, repeat your private paths in it. ## Cloudflare's managed robots.txt and Content Signals 3.1% of Polish sites serve [Cloudflare's managed robots.txt](https://developers.cloudflare.com/bots/additional-configurations/managed-robots-txt/): one switch in the dashboard, and the CDN puts a block of rules in front of the site's own file and keeps it up to date. The block disallows exactly the eight training crawlers in our list, from GPTBot to Amazonbot, and no search crawler. Those sites, among them the Polska Press regional titles such as poranny.pl, nto.pl, pomorska.pl and gazetawroclawska.pl, make up 15.1% of all Polish blockers and 24% of the sites that block training only. They are part of why Poland leans that way, though not all of it: take them out and training-only blocks are still more common than in the global sample, where we found no managed file at all. Large international sites write their own. The switch shows in the numbers. Behind Cloudflare, 25.6% of Polish sites block AI crawlers, against 18.2% elsewhere. Globally it is the other way round. **In Poland, sites behind Cloudflare block more** (Share blocking at least one AI crawler, by whether the site is served through Cloudflare) | Item | Behind Cloudflare | Other hosting | | --- | --- | --- | | Poland | 26% | 18% | | Global | 19% | 24% | Source: Outofplace crawl, 23 Sept 2026. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/en/chart-in-poland-sites-behind-cloudflare-block-more.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/domains.csv The managed file also carries a `Content-Signal` line (`search=yes, ai-train=no`), part of the [Content Signals Policy](https://contentsignals.org/) Cloudflare published in September 2025 for saying what content may be used for: search, AI input, AI training. 3.9% of Polish sites say `ai-train=no` this way, against 1.6% globally. If a robots.txt tester flags `Content-Signal` as an unknown directive, that is expected and harmless: under RFC 9309 a crawler skips lines it doesn't recognise. 79% of those lines come from the managed file, not from anyone typing them. ## What is llms.txt, and who has one? [`llms.txt`](https://llmstxt.org) is a Markdown file that tells language models what a site is and where its important pages are, [proposed by Jeremy Howard](https://www.answer.ai/posts/2024-09-03-llmstxt.html) in September 2024. The spec asks only for an H1 with the site's name; we also required at least one link, since a file without one points nowhere. 9.2% of the Polish sample serve such a file at `/llms.txt`. Another 10% answer `/llms.txt` with an HTML page and a 200 status, which is what a model reading it receives instead, and what a careless checker counts as "has llms.txt". Hosting companies got there first: home.pl, nazwa.pl, cyberfolks.pl, dhosting.pl and kei.pl all serve a valid file, and so do mbank.pl, t-mobile.pl, rossmann.pl, mediamarkt.pl and, among public bodies, uokik.gov.pl. Google has said [its Search ignores the file](https://developers.google.com/search/docs/fundamentals/ai-optimization-guide?hl=en); it is there for the other assistants. We serve one ourselves: [our llms.txt](https://www.outofplace.space/llms.txt) lists our studies, case studies and services, and [llms-full.txt](https://www.outofplace.space/llms-full.txt) carries the full text of every post. **Most sites have no llms.txt; one in ten answer with a web page** (What GET /llms.txt returned · n = 1,000 per sample · errors and paths our crawler was asked not to fetch count as none) | Item | Valid llms.txt | Wrong format | HTML page (soft 404) | None | n | | --- | --- | --- | --- | --- | --- | | Top 1,000 .pl | 9.2% | 2.4% | 10% | 78% | 1,000 | | Global top 1,000 | 14% | 3.4% | 9.6% | 74% | 1,000 | Source: Outofplace crawl, 23 Sept 2026. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/en/chart-most-sites-have-no-llms-txt-one-in-ten-answer-with-a-web-page.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/domains.csv ## The rest of the machine-readable web Crawlers read more than robots.txt. Here Polish sites are close to the world on the basics and behind on the details that help a machine place a page: [`hreflang` alternates](https://developers.google.com/search/docs/specialty/international/localized-versions?hl=en), and [a sitemap listed where crawlers look for it](https://www.sitemaps.org/protocol.html#submit_robots). [Zstandard compression](https://www.rfc-editor.org/rfc/rfc8878.html) is several times more common on .pl homepages, but that is Cloudflare again: all but one of the Polish sites that sent it came through the CDN. ## Three policies worth copying Some Polish sites have clearly thought about it. We checked each of these files by hand on the day of the crawl. - **Training no, answers yes.** The Wirtualna Polska titles (wp.pl, o2.pl, money.pl, pudelek.pl, abczdrowie.pl, dobreprogramy.pl) [disallow GPTBot, CCBot and Bytespider](https://www.wp.pl/robots.txt), and give OAI-SearchBot, ChatGPT-User, PerplexityBot and Perplexity-User their own `Allow: /` groups. A publisher saying exactly what it wants. - **Everyone welcome, by name.** mediamarkt.pl and euro.com.pl have [`Allow: /` groups](https://mediamarkt.pl/robots.txt) for GPTBot, ClaudeBot, OAI-SearchBot, Claude-SearchBot, PerplexityBot and more. For a retailer, an assistant that recommends a product is a shop window. - **Let the CDN keep the list.** The Polska Press regional titles use Cloudflare's managed file, which blocks the training crawlers and stays current without anyone editing it. ## How to block AI crawlers in robots.txt ### Should you block AI crawlers? There is no single right policy. A publisher that sells its archive has different interests from a shop that wants to be recommended. But whichever you choose, choose by purpose, not by vendor: ### A robots.txt that blocks AI training and keeps AI search This is the shape of a robots.txt that blocks training and keeps AI search. The training group is the same eight crawlers Cloudflare's managed file blocks. Our own site does the opposite and [lets every crawler in](https://www.outofplace.space/robots.txt), because being cited is the point of a studio blog. ```txt title="robots.txt" # AI search and user-triggered fetches: they cite and link to you User-agent: OAI-SearchBot User-agent: ChatGPT-User User-agent: Claude-SearchBot User-agent: Claude-User User-agent: PerplexityBot User-agent: Perplexity-User Allow: / # Named groups don't inherit from *, so repeat private paths Disallow: /cart/ Disallow: /account/ # Model training User-agent: GPTBot User-agent: ClaudeBot User-agent: Google-Extended User-agent: Applebot-Extended User-agent: CCBot User-agent: Bytespider User-agent: meta-externalagent User-agent: Amazonbot Disallow: / # Everyone else, including Googlebot and Bingbot User-agent: * Disallow: /cart/ Disallow: /account/ Sitemap: https://www.example.pl/sitemap.xml ``` **1. Decide per purpose.** Training, AI search, user-triggered fetches. Write down what you want for each before you touch the file. **2. Name the current tokens.** Take them from [the vendors' own pages](#further-reading), not from a list someone posted in 2023. **3. Repeat private paths in every named group.** A crawler that matches a named group ignores `User-agent: *` entirely. **4. Test it.** Paste the file into the checker below and look at the paths that matter to you. **5. Cover the crawlers robots.txt can't.** Copilot rides on Bingbot, so its controls are the [`noarchive` and `nocache` meta tags](https://www.bing.com/webmasters/help/robots-meta-tags-and-attributes-that-bing-supports-5198d240). Google's AI Overviews follow Googlebot and [snippet controls such as `nosnippet`](https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag?hl=en). Fetchers that may ignore robots.txt need a CDN or server rule if they must be stopped. **6. Check it every quarter.** New agents appear a few times a year. A stale list is worse than none, because it looks like a decision. Paste your robots.txt here to see what each AI crawler may fetch. It runs in your browser on the same parser we used for the study; nothing is sent anywhere. ## How we measured We took the [Tranco list Y8YYG](https://tranco-list.eu/list/Y8YYG/full) (created 22 September 2026, 30-day window, five providers) and walked it from the top, keeping the first 1,000 registrable .pl domains whose server answered. The global control is the first 1,000 domains of the same list, processed the same way. On 23 September our crawler fetched each domain's robots.txt and homepage, plus `/llms.txt`, `/llms-full.txt` and the sitemap, identifying itself as `OutofplaceResearchBot` with a link to a page explaining the study. Each robots.txt was parsed under RFC 9309 and evaluated for the homepage path `/` for 38 user agents: 36 AI crawlers of 17 operators, retired names included, plus Googlebot and Bingbot for reference. The charts show the tokens each operator currently documents. A crawler counts as blocked when the rule that applies to it disallows `/`, whether it is named or falls back to `*`. Shares have 95% Wilson intervals; differences between the samples, Newcombe intervals. The sample is the first 1,000 .pl domains in the Tranco list that answered our requests. 23 of them disallow our crawler from their homepage in robots.txt; we still read their robots.txt (it is public by definition) but fetched nothing else. Domains that failed DNS, refused connections or returned server errors were skipped and replaced by the next one on the list. With 1,000 sites, the 95% interval around the headline share runs from 18.1% to 23.1%. Each site gets one class, first match wins. Blanket block: Googlebot is blocked too, so the rule is not about AI. All AI: every training crawler and at least one search crawler or fetcher are blocked. Stale list: a name the vendor no longer documents is blocked, while the crawler that replaced it is not. Training only: training crawlers blocked, no search crawler or fetcher. Inconsistent: a search crawler or fetcher is blocked while a training crawler is let through. Open: no AI crawler blocked. The rules and their tests are in the repository. robots.txt is only what a site asks for. Some sites block AI crawlers at the firewall or CDN instead, and some serve a bot challenge to every crawler; we counted challenges separately and never as "allowed". We evaluated the homepage path only: a site that blocks AI crawlers from its articles but not from `/` counts as open. A .pl domain is not the same as a Polish business, and popularity lists favour big sites. The numbers describe the most visited part of the .pl web on one day. ## Further reading - [RFC 9309: Robots Exclusion Protocol](https://www.rfc-editor.org/rfc/rfc9309.html): The standard for robots.txt: groups, matching and what a crawler must do when the file is missing or unreachable. - [OpenAI: Overview of OpenAI crawlers](https://developers.openai.com/api/docs/bots): GPTBot, OAI-SearchBot and ChatGPT-User, and what each is used for. - [Anthropic: How site owners can block the crawlers](https://support.claude.com/en/articles/8896518-does-anthropic-crawl-data-from-the-web-and-how-can-site-owners-block-the-crawler): ClaudeBot, Claude-SearchBot and Claude-User. - [Google: Common crawlers, including Google-Extended](https://developers.google.com/crawling/docs/crawlers-fetchers/google-common-crawlers?hl=en): What Google-Extended controls, and what it doesn't. - [Cloudflare: Managed robots.txt](https://developers.cloudflare.com/bots/additional-configurations/managed-robots-txt/): What the one-click file blocks, and the Content-Signal line it adds. - [llms.txt: the proposal and its format](https://llmstxt.org): The original specification: where the file lives and how it is structured. - [OutofplaceResearchBot: what it fetches and how to block it](https://www.outofplace.space/bot): Who runs our crawler, how it identifies itself and how politely it crawls. --- # Next.js prefetch, measured: Partial Prefetching in 16.3 (EN) Source: https://www.outofplace.space/blog/nextjs-prefetch-benchmark · Published 2026-09-23 Category: Performance · Tags: Next.js, Prefetching, React > Partial Prefetching in Next.js 16.3 cut prefetched bytes by up to 93% in our benchmark, but URL content now lands after the click. When each setup wins. [Next.js 16.3](https://nextjs.org/blog/next-16-3) changes what Next.js prefetch means. With [`partialPrefetching`](https://nextjs.org/docs/app/api-reference/config/next-config-js/partialPrefetching) on, the [App Router](https://nextjs.org/docs/app) no longer fetches a payload for every link on screen: it fetches one reusable shell per route and leaves the URL-specific content for after the click. We built one app six ways and clicked through it 3,744 times to see what that trade buys and what it costs. On a docs page with a 100-link sidebar, prefetched bytes fell by 93%. The price is time: the content that used to be on screen almost at once now arrives a few hundred milliseconds after the click, behind a skeleton. Which side of that trade you want depends on the page, and on [one detail of React that is easy to miss](#the-skeleton-you-will-see-300-ms). - Partial Prefetching cut prefetched bytes by 78–93% on link-heavy pages, and a whole docs navigation by about eleven times. - The shell paints instantly. The URL content arrives after the click: 345ms on docs against 52ms with Cache Components alone, on a throttled phone. - A skeleton that appears stays for about 300 ms, because React holds each reveal for that long. - Links with `prefetch={true}` stay instant in every setup. - Keep `prefetchInlining` at its default; HTTP/2 changed nothing that matters. ## What Partial Prefetching changes Until 16.3, the App Router prefetched per link: as N links scrolled into view, it fetched about N route payloads. With `partialPrefetching` (it requires [`cacheComponents`](https://nextjs.org/docs/app/api-reference/config/next-config-js/cacheComponents)), it fetches one [App Shell](https://nextjs.org/docs/app/guides/adopting-partial-prefetching) per route: everything the page renders that doesn't depend on the URL. Links to the same route share that one prefetch. Content that reads `params` or `searchParams` resolves after the click, unless a link asks for more with `prefetch={true}`. We compared six builds of the same app: - **L0**, no Cache Components: the classic App Router. - **C0**, Cache Components alone. - **P0**, Cache Components with Partial Prefetching and the default prefetch inlining. - **P1–P3**, the same with inlining off, with small thresholds and with large ones. Each was clicked through three navigations: a catalog of 48 products to a product page, a docs page with a 100-link sidebar to another docs page, and a search results page to another search through one of eight `prefetch={true}` links. ## Prefetch bytes: up to 93% fewer On the docs page, Cache Components alone prefetched every visible sidebar link. Partial Prefetching took that from 402 kB → 29 kB (−93%), in 8.5 requests instead of 49. On the catalog the saving was 78%. Search barely moved, because its eight `prefetch={true}` links still fetch their own results. **Partial Prefetching prefetches a fraction of the bytes on link-heavy pages** (Compressed RSC bytes prefetched before the click · desktop, unthrottled, warm · medians of 20 runs) | Item | Catalog → product | Docs → docs | Search → search | | --- | --- | --- | --- | | L0 · Classic router | 30 kB | 408 kB | 98 kB | | C0 · Cache Components | 160 kB | 402 kB | 163 kB | | P0 · Partial Prefetching | 34 kB | 29 kB | 107 kB | | P1 · Inlining off | 33 kB | 32 kB | 105 kB | | P2 · Small inlining | 32 kB | 28 kB | 103 kB | | P3 · Large inlining | 34 kB | 33 kB | 105 kB | Source: Outofplace benchmark, Next.js 16.3.6. Chart: https://www.outofplace.space/data/blog/nextjs-prefetch-benchmark/charts/en/chart-partial-prefetching-prefetches-a-fraction-of-the-bytes-on-link-h.png Data: https://www.outofplace.space/data/blog/nextjs-partial-prefetching-benchmark/2026-09-23/summary_by_variant.csv One row deserves a second look. Turning on Cache Components without Partial Prefetching made the catalog prefetch five times more than the classic router, 30 kB → 160 kB (+426%): its prerendered product shells become prefetchable per link. If you adopt Cache Components on link-heavy pages, decide on Partial Prefetching at the same time. ## Is navigation actually instant? The shell is. Under Partial Prefetching it painted 43ms–45ms after the click on a throttled phone. The part people came for, the product or the article, is another story: it needs a request after the click. **Cache Components alone shows the content at once; Partial Prefetching after a round trip** (Click to the first frame with the URL-specific content · mobile, Lighthouse-mobile throttling, warm click · ms) | Item | L0 · Classic router | C0 · Cache Components | P0 · Partial Prefetching | | --- | --- | --- | --- | | Catalog → product | 375ms | 60ms | 262ms | | Docs → docs | 47ms | 52ms | 345ms | | Search → search | 40ms | 41ms | 43ms | Source: Outofplace benchmark, Next.js 16.3.6. Chart: https://www.outofplace.space/data/blog/nextjs-prefetch-benchmark/charts/en/chart-cache-components-alone-shows-the-content-at-once-partial-prefetc.png Data: https://www.outofplace.space/data/blog/nextjs-partial-prefetching-benchmark/2026-09-23/summary_by_variant.csv On docs, Cache Components alone painted the new article in 52ms; Partial Prefetching took 345ms. On the product page the gap was smaller, 60ms → 262ms (+337%), and the classic router was slowest of all, because it had nothing prerendered for the dynamic route. Search, where every link carries `prefetch={true}`, painted in 40ms–43ms in every setup. ### The skeleton you will see: 300 ms On the product page the three stages land one after another: the shell, the product, then the part rendered at request time. **Under Partial Prefetching the page arrives in three steps** (Catalog → product · mobile, throttled, warm · click to each stage on screen · ms) | Item | Shell | Content | Request-time part | | --- | --- | --- | --- | | L0 · Classic router | 375ms | 375ms | 375ms | | C0 · Cache Components | 60ms | 60ms | 342ms | | P0 · Partial Prefetching | 47ms | 262ms | 562ms | Source: Outofplace benchmark, Next.js 16.3.6. Chart: https://www.outofplace.space/data/blog/nextjs-prefetch-benchmark/charts/en/chart-under-partial-prefetching-the-page-arrives-in-three-steps.png Data: https://www.outofplace.space/data/blog/nextjs-partial-prefetching-benchmark/2026-09-23/summary_by_variant.csv On docs, the skeleton stayed up 298ms in every Partial Prefetching build. That is not network time: the response had arrived after 250ms. The React build inside Next.js 16.3.6 (`19.3.0-canary`) [waits until 300 ms](https://github.com/react/react/blob/d083ec1da1e5252abd3ddfdde6dfbc09701a2c51/packages/react-reconciler/src/ReactFiberWorkLoop.js#L528) after the last switch between a [Suspense](https://react.dev/reference/react/Suspense) fallback and its content before it commits the next one, so a loading state doesn't flash. The side effect: stages chain. A skeleton that appears is on screen for about 300 ms even when the data is already there, and a separate boundary for request-time data reveals 300 ms after the one before it. Design skeletons to be looked at, and consider one boundary where two would only chain. ### An early click Clicking 50 ms after the page hydrates, before any prefetch finishes, takes the advantage away from everyone who prefetches. Cache Components alone is as slow as Partial Prefetching then, because both show a fallback first and then wait out the 300 ms. **Clicked early, no setup has prefetched yet** (Click 50 ms after hydration · mobile, throttled · click to URL content · ms) | Item | L0 · Classic router | C0 · Cache Components | P0 · Partial Prefetching | | --- | --- | --- | --- | | Catalog → product | 367ms | 374ms | 389ms | | Docs → docs | 262ms | 528ms | 529ms | | Search → search | 234ms | 404ms | 339ms | Source: Outofplace benchmark, Next.js 16.3.6. Chart: https://www.outofplace.space/data/blog/nextjs-prefetch-benchmark/charts/en/chart-clicked-early-no-setup-has-prefetched-yet.png Data: https://www.outofplace.space/data/blog/nextjs-partial-prefetching-benchmark/2026-09-23/summary_by_variant.csv The last stage, the part rendered at request time, splits these clicks in two. With Partial Prefetching, 6 of 12 early clicks on the product page had the whole page on screen after 375ms–400ms. The other 6 took 650ms–700ms, and no run landed in between. The gap is about the 300 ms React waits between two reveals: the last stage arrives with the product or one wait later. **The last stage lands with the product or about 300 ms later** (Catalog → product, early click · Partial Prefetching · mobile, throttled, HTTP/2 run · click to the last stage on screen · ms) | Range | runs | | --- | --- | | 375ms–400ms | 6 | | 400ms–425ms | 0 | | 425ms–450ms | 0 | | 450ms–475ms | 0 | | 475ms–500ms | 0 | | 500ms–525ms | 0 | | 525ms–550ms | 0 | | 550ms–575ms | 0 | | 575ms–600ms | 0 | | 600ms–625ms | 0 | | 625ms–650ms | 0 | | 650ms–675ms | 3 | | 675ms–700ms | 3 | Source: Outofplace benchmark, Next.js 16.3.6. Chart: https://www.outofplace.space/data/blog/nextjs-prefetch-benchmark/charts/en/chart-the-last-stage-lands-with-the-product-or-about-300-ms-later.png Data: https://www.outofplace.space/data/blog/nextjs-partial-prefetching-benchmark/2026-09-23/runs.csv ## The whole bill Partial Prefetching moves bytes from before the click to after it, and on the product page it also doubles them: the navigation response carried two complete copies of the product's payload, 13 kB → 26 kB (+99%) compressed. Counting everything a navigation downloads, prefetch included, it still comes out far ahead on docs. **A whole docs navigation costs about a tenth of the bytes** (All compressed RSC bytes of one docs navigation, prefetch and navigation · mobile, throttled, warm) | Item | Value | n | | --- | --- | --- | | L0 · Classic router | 463 kB | 20 | | C0 · Cache Components | 458 kB | 20 | | P0 · Partial Prefetching | 40 kB | 20 | | P1 · Inlining off | 43 kB | 20 | | P2 · Small inlining | 39 kB | 20 | | P3 · Large inlining | 44 kB | 20 | Source: Outofplace benchmark, Next.js 16.3.6. Chart: https://www.outofplace.space/data/blog/nextjs-prefetch-benchmark/charts/en/chart-a-whole-docs-navigation-costs-about-a-tenth-of-the-bytes.png Data: https://www.outofplace.space/data/blog/nextjs-partial-prefetching-benchmark/2026-09-23/summary_by_variant.csv About 11 times fewer bytes on docs, 2.2 times fewer on the catalog. Hydration and input delay on the start page didn't change in any setup. ## When `prefetch={true}` is worth it [``](https://nextjs.org/docs/app/api-reference/components/link#prefetch) fetches the destination's URL data too, so its click is as instant as a full prefetch. It is paid per visible link: the eight search links cost 107 kB, more than the whole docs page under Partial Prefetching. Use it where the click is likely and the data cacheable: search suggestions, a "next" link, the first few results. On grids of cards, prefetch on intent (hover or touch) instead of marking every card. ## prefetchInlining: leave it on [`experimental.prefetchInlining`](https://nextjs.org/docs/app/api-reference/config/next-config-js/prefetchInlining) bundles small prefetch responses into one. The default and our two threshold settings differed by at most one request and a few kilobytes, with no measurable difference in time. Turning inlining off added five or six requests on the catalog and search, and over HTTP/1.1 that cost an early click on the catalog: six connections per host fill up. Over [HTTP/2](https://www.rfc-editor.org/rfc/rfc9113.html) the penalty disappeared. Every other setup was the same on both protocols. **HTTP/2 only matters with inlining turned off** (Catalog → product, early click · mobile, throttled · click to content · HTTP/1.1 and HTTP/2 interleaved, 12 runs each · ms) | Item | HTTP/1.1 | HTTP/2 | | --- | --- | --- | | L0 · Classic router | 365ms | 363ms | | C0 · Cache Components | 375ms | 373ms | | P0 · Partial Prefetching | 387ms | 386ms | | P1 · Inlining off | 440ms | 372ms | | P2 · Small inlining | 390ms | 383ms | | P3 · Large inlining | 387ms | 386ms | Source: Outofplace benchmark, Next.js 16.3.6. Chart: https://www.outofplace.space/data/blog/nextjs-prefetch-benchmark/charts/en/chart-http-2-only-matters-with-inlining-turned-off.png Data: https://www.outofplace.space/data/blog/nextjs-partial-prefetching-benchmark/2026-09-23/summary_by_variant.csv ## Which setup to choose ```ts title="next.config.ts" const nextConfig: NextConfig = { cacheComponents: true, // One App Shell per route instead of one prefetch per link. partialPrefetching: true, }; ``` ```tsx title="The links where a wait would hurt" {suggestion} ``` **1. Count the links.** Pages with many links to the same dynamic route (docs, grids, feeds) gain the most. A page with a handful of links to different pages gains little. **2. Decide per route.** Where instant content matters more than bytes and the pages are static, keep a route on full prefetch; elsewhere turn Partial Prefetching on. The [segment config `export const prefetch = 'partial'`](https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config/prefetch) adopts it one route at a time. **3. Mark the likely clicks.** Add `prefetch={true}` where the next click is predictable and the data cacheable. **4. Design the skeleton.** It will be seen for about 300 ms on a slow connection. Put the title and navigation in the part that doesn't depend on the URL: it paints almost at once. This site runs Partial Prefetching: most of our pages have few links, and the ones that have many (the blog, the case studies) are static and small. Our own products, Portivo, Sprawna Matura and Levera, are built on Next.js too. ## How we measured A generated App Router app (a 48-product catalog, 100 docs pages with a sidebar in the layout, a search page) was built six times with Next.js 16.3.6, differing only in `cacheComponents`, `partialPrefetching` and `experimental.prefetchInlining`, and served with `next start`. Headless Chrome opened a start page in a fresh browser context, waited, and clicked a link, recording every request over the [DevTools protocol](https://chromedevtools.github.io/devtools-protocol/) and timing marker elements from the click event to the next animation frame. Each combination of setup, scenario, phone or desktop, fast or [throttled network (150 ms, 1.6 Mbps, 4× CPU)](https://github.com/GoogleChrome/lighthouse/blob/main/docs/throttling.md) and early or late click ran 20 times in shuffled order, 2,880 runs; an HTTP/2 arm added 864 more. Medians carry seeded bootstrap 95% intervals. It is a lab: one machine, localhost, no CDN, no images or fonts, generated text, and a synthetic 300 ms request-time delay. Throttling is per request, not packet-level, so absolute times are optimistic; the comparisons are what count. A late click is the best case for prefetching and an early one a specific race; real users click everywhere in between. The App Shell mechanics, the doubled product payload and the 300 ms reveal are specific to Next.js 16.3.6 and its React canary and may change in a patch release. The shared shell is fetched through the URL of whichever link the router schedules first, and that response carries the whole page for that URL. A click on exactly that link needs no request at all. We picked click targets further down the page so that this didn't flatter Partial Prefetching. ## Further reading - [Next.js: Adopting Partial Prefetching](https://nextjs.org/docs/app/guides/adopting-partial-prefetching): How the App Shell works and how to move routes over one at a time. - [Next.js: Optimizing prefetching](https://nextjs.org/docs/app/guides/optimizing-prefetching): Per-link prefetching with prefetch={true}, and when to use it. - [Next.js: prefetchInlining](https://nextjs.org/docs/app/api-reference/config/next-config-js/prefetchInlining): What inlining bundles, and why the default is right for most apps. --- # Outofplace powołuje Portivo Inc., pierwszą spółkę zależną (PL) Source: https://www.outofplace.space/pl/aktualnosci/portivo-inc · Published 2026-09-30 > Outofplace powołało Portivo Inc., spółkę w całości zależną, dla Portivo: systemu dla firm czarterowych i pierwszego produktu, który studio zbudowało dla siebie. ## Nie kończymy na projekcie. Budujemy firmy. Każdy produkt prowadzimy tak, jakby był naszą firmą. Portivo jako pierwsze nią zostało. **Co się zmienia.** Portivo Inc. to spółka z Delaware, w całości należąca do Outofplace Poland sp. z o.o. Ma pełnię praw do Portivo: kodu, marki i portivo.eu. Outofplace staje się spółką matką grupy. **Co to znaczy dla naszych klientów.** Wszystko, czego uczymy się na własnych produktach, trafia do projektów, które robimy z klientami. Ten sam zespół i ten sam standard, sprawdzone w firmie, w której całe ryzyko jest nasze. - **100%** Własność Outofplace. Portivo Inc. ma jednego właściciela: studio. - **7000+** Commitów. Od pierwszej linii kodu, w niecałe 15 miesięcy. - **8900+** Testów automatycznych. Każda zmiana przechodzi je przed wdrożeniem. ## Bez skrótów. Nawet tam, gdzie nikt nie zagląda. Portivo zaczęło się w lipcu 2025 od jednego pytania: dlaczego firma czarterowa wciąż działa na arkuszach, przelewach i kartce na pomoście? Odpowiedzieliśmy tak, jak zawsze: najpierw praca, potem ekrany. **Baza danych mówi nie.** Jednego jachtu nie da się zarezerwować dwa razy na te same dni. Drugą rezerwację odrzuca sama baza danych, bez względu na ekran, aplikację czy gorącą sobotę w marinie. **Każdy złoty się zgadza.** Płatności, kaucje i prowizje przechodzą przez księgę z podwójnym zapisem. W każdym zapisie winien równa się ma, inaczej zapis nie powstaje. Nikt niczego nie zaokrągla ręcznie. **Faktury trafiają do KSeF.** Faktury, korekty i miesięczna paczka dla księgowości powstają z tych samych zapisów, a każda faktura trafia prosto do KSeF, czyli krajowego systemu faktur. **Najpierw rysunek, potem kod.** Każdy ekran najpierw projektujemy, a potem budujemy dokładnie według projektu, co do piksela: w przeglądarce, na tablecie i w telefonie, po polsku i po angielsku. ## Zbudowane, żeby zmienić całą branżę wodną. Jeden system do prowadzenia firmy czarterowej: flota, rezerwacje, płatności, umowy, protokoły i faktury, a do tego własna strona rezerwacji dla każdej firmy. **Własna strona rezerwacji.** Gość wybiera termin, płaci zaliczkę BLIK-iem lub kartą i dostaje potwierdzenie. Rezerwacja jest już w kalendarzu. **Weryfikacja tożsamości.** Gość skanuje dokument i robi selfie własnym telefonem. Twarz jest porównana z dokumentem, zanim ktokolwiek wejdzie na pokład. **Portivo POS.** Kasa przy kei: karta na czytniku, BLIK albo link do płatności. Wpłata od razu trafia do rezerwacji, a paragon prosto do gościa. **Rezerwacja od początku do końca.** Umowa podpisana online, tożsamość potwierdzona, dopłata pobrana w terminie, faktura końcowa w KSeF. Każdy krok odhacza się sam. **Protokół zdawczo-odbiorczy.** Przy odbiorze tablet zestawia każdą burtę ze zdjęciami z ostatniego zdania jachtu i wskazuje, co się zmieniło. **Portivo Operator.** Rezerwacje, kalendarz, płatności, kasa i aktywność dnia, wszystko w telefonie armatora, gdziekolwiek akurat jest. ## Dla mediów **O Outofplace.** Outofplace to niezależne studio produktowe. Projektuje i buduje produkty cyfrowe dla klientów i dla siebie, od pierwszego szkicu do firmy, która na nich działa. **O Portivo Inc..** Portivo Inc. rozwija i sprzedaje [Portivo, system do prowadzenia firmy czarterowej](https://portivo.eu). To spółka z Delaware, w całości należąca do Outofplace Poland sp. z o.o. **Kontakt dla mediów.** Marcel Bogdan, Managing Partner. Napisz na [contact@outofplace.space](mailto:contact@outofplace.space) albo zadzwoń: [+48 502 856 472](tel:+48502856472). Odpowiadamy w ciągu jednego dnia roboczego. --- # Pod (PL) Source: https://www.outofplace.space/pl/praca/pod Pod to nasz własny produkt: IDE na macOS, w którym wielu agentów kodujących pracuje obok siebie na jednym Macu. Na razie to narzędzie wewnętrzne: używamy go w studiu, a poza nim nie jest dostępny. - **Co:** IDE dla floty agentów kodujących, w natywnym oknie macOS, z natywnym terminalem i wbudowanym claude-acc. - **Status:** wersja wewnętrzna. Trzecia wersja kandydująca Poda 1.0, 1.0.0-rc3, działa na naszych Macach. ## Kontekst Na własnych Macach uruchamiamy wielu agentów kodujących naraz, a flota mocno obciąża komputer: tekst zalewa terminale, subskrypcje dochodzą do limitów, serwery deweloperskie zjadają pamięć, a buildy się piętrzą. Na takie obciążenie zbudowaliśmy claude-acc. W Podzie jest częścią IDE, obok natywnego terminala. ## Co jest w środku - **Natywne okno:** pasek boczny, karty w pasku tytułu i panele to SwiftUI i AppKit. Każdy projekt ma jeden spokojny wiersz, a każdy agent jeden mały znacznik: pracuje, czeka na ciebie albo skończył. - **Natywny terminal:** każdy panel to natywny widok z silnikiem Ghostty, rysowany przez Metal, a nie strona internetowa. - **Wbudowany claude-acc:** rotacja subskrypcji, strażnik pamięci dla serwerów deweloperskich, buildy kolejkowane według wolnej pamięci, sprzątanie, blokada uśpienia i sterowanie wentylatorami. - **Bez telemetrii:** Pod niczego nie wysyła. Nie ma telemetrii, relaya, powiadomień push, udostępniania ani zbierania opinii. Po wersji 1.0 przyjdą: indeksowane wyszukiwanie kodu dla agentów, środowiska w maszynach wirtualnych OrbStack i Pod Workspace, zarządzany katalog na repozytoria. ## Technologia | Narzędzie | Co robi w Podzie | | :--- | :--- | | Swift, SwiftUI, AppKit | Okno i jego interfejs | | Ghostty, Metal | Natywny terminal: silnik Ghostty rysowany przez Metal | | Electron, TypeScript, React | Runtime za oknem: projekty, worktree, agenci i sesje terminali | | Python | claude-acc | ## Stan dziś Pod 1.0 jest na razie narzędziem wewnętrznym studia. Jego trzecia wersja kandydująca, 1.0.0-rc3, działa na naszych Macach. - [Pod](https://pod.codes): IDE dla floty agentów na macOS. --- # Nowości web dev: Next.js 16.4.3, budżet Vercel, Agent Skills (PL) Source: https://www.outofplace.space/pl/blog/nowosci-web-dev-2026-10-25 · Published 2026-10-25 Category: AI dla programistów · Tags: Next.js, Claude, agenci AI > Nowości web dev z 18–25 października 2026: Next.js 16.4.3 odchudza proxy.ts, Vercel CLI ustawia limit wydatków, OIDC zamiast kluczy, Agent Skills w AAIF. W nowościach web dev z tego tygodnia chodzi głównie o dane dostępowe i agentów, a nie o zmiany łamiące zgodność. [Next.js 16.4.3](https://github.com/vercel/next.js/releases/tag/v16.4.3) (23 października 2026) to łatka z poprawkami błędów, bez poprawek bezpieczeństwa, więc po zeszłotygodniowych [łatkach na RCE w React i Next.js](https://www.outofplace.space/pl/blog/nowosci-web-dev-2026-10-18) możesz ją wdrożyć we własnym tempie. Vercel cały tydzień zajmował się dostępem: budżety wydatków z CLI, termin dla integracji z Marketplace, które wciąż używają długoterminowych kluczy, i opis tego, jak jego własny agent dotyka produkcji. Anthropic oddał standard Agent Skills fundacji Agentic AI Foundation, a jego nowa wersja API przyszła razem z SDK, które łamią kod; to opisujemy w [aktualizacji Anthropic SDK do wersji API 2026-10-21](https://www.outofplace.space/pl/blog/anthropic-sdk-migracja-api-2026-10-21). | Co | Wersja lub data | Co zrobić | | ----------------------------------- | ----------------------- | ------------------------------------------------------------------ | | Next.js | 16.4.3, 23 paź | Zwykła łatka; lżejsze proxy.ts i spójne ślady | | Limit wydatków w Vercel CLI | 23 paź | Ustaw budżet w CI albo skrypcie; o `--pause` decyduj świadomie | | Długoterminowe statyczne klucze | 22 paź, termin 30 lis | Przenieś klucze chmurowe na OIDC; sprawdź integracje z Marketplace | | Vercel Agent na produkcji | 23 paź | Skopiuj wzorzec zatwierdzania planu do własnych agentów | | Zgłoszenia z Vercel MCP | 23 paź | Zgłaszaj błędy z poziomu agenta, który na nie trafił | | Agent Skills w AAIF | 22 paź | Nic się nie psuje; śledź specyfikację na agentskills.io | | Claude API i SDK | 21 i 22 paź | Aktualizuj SDK celowo; sprawdzaj pola blokad klientów | ## Next.js ### Next.js 16.4.3: lżejsze proxy.ts i ślady OpenTelemetry w jednym kawałku Next.js 16.4.3 ukazał się 23 października 2026 jako backport ośmiu zmian z canary; żadna nie jest poprawką bezpieczeństwa. Dla działających aplikacji liczą się dwie. [Don't load the app-page runtime in proxy.ts](https://github.com/vercel/next.js/pull/100423) sprawia, że import czegokolwiek z `next/server` nie wciąga już runtime’u stron App Routera ważącego 688 KB. Backport przytacza pomiar z pierwotnego pull requesta, zrobiony na canary na minimalnym proxy, nie na 16.4.3 i nie przez nas: zimny start spadł z 53,8 ms do 39,1 ms, a ładowany JavaScript z 1466 KB do 748 KB. [Keep OpenTelemetry request traces together](https://github.com/vercel/next.js/pull/100542) składa przygotowanie trasy, middleware i render jednego żądania z powrotem w jeden ślad i naprawia middleware w Node.js, które gubiło kontekst rodzica (regresja z 16.3). Reszta: adresy Google Fonts bez rozszerzenia działają w obu bundlerach, cofnięto zmianę unieważniania loaderów w Turbopacku, start serwera nie ładuje już osobnej kopii Reacta, do tego zmiany w procesie wydawniczym i testach. Nasze zdanie: jeśli Twoje proxy działa przy każdym żądaniu, mniejszy bundel to darmowy zysk na zimnym starcie, a jeśli wysyłasz ślady do backendu OpenTelemetry, żądania przestaną się rozpadać na kilka osieroconych śladów. Nic z tego nie jest pilne; przejdź z 16.4.2 przy najbliższym wdrożeniu. ## Vercel ### Vercel CLI dostaje zarządzanie wydatkami: `vercel budgets` Od 23 października 2026 [Vercel CLI zarządza budżetem On-Demand zespołu](https://vercel.com/changelog/vercel-cli-adds-spend-management), tym samym, który widać w ustawieniach rozliczeń. `vercel budgets` pokazuje bieżące wydatki, aktywny budżet i trzy ostatnie alerty; `vercel budgets set --amount ` go ustawia (`--scope ` wybiera zespół); `vercel budgets remove --yes` go usuwa; `vercel budgets alerts` wypisuje historię alertów z `--since`, `--until`, `--limit` i `--json`. Sam budżet tylko powiadamia. Z `--pause` produkcyjne wdrożenia wszystkich projektów zespołu wstrzymują się przy 100% budżetu i przestają być dostępne. Potrzebna jest rola Owner albo Billing; funkcja nic nie kosztuje w planie Pro i w Enterprise z planem Flexible Commitment. Nasze zdanie: budżet to teraz jedna linijka w skrypcie zakładającym zespół, więc każdy nowy zespół może zaczynać z limitem. `--pause` traktuj jako decyzję o przestoju, nie o pieniądzach: zdejmuje produkcję, więc stosuj go przy projektach pobocznych i demach, a przy wszystkim, co zarabia, zostaw budżet tylko z alertami. ### Vercel wyznacza termin dla długoterminowych statycznych kluczy W tekście [Death to long-lived static credentials](https://vercel.com/blog/death-to-long-lived-static-credentials) z 22 października 2026 Malte Ubl przekonuje, że klucze API i hasła do baz danych powinny domyślnie ustąpić krótkotrwałym tokenom opartym na tożsamości, i przytacza badanie ponad 1000 dostawców SaaS, z których 8,4% obsługiwało takie uwierzytelnianie. Tekst wymienia, co Vercel oferuje dziś: federację OIDC (aplikacja wymienia token tożsamości wydany przez Vercel na tymczasowe dane dostępowe AWS, Google Cloud albo Azure na zasadach zaufania ustawionych dla projektu i środowiska; ogólnie dostępna od 2024), OIDC dla Vercel Blob, AI Gateway i Sandbox, własnych odbiorców (audience) tokenów oraz Vercel Connect dla aplikacji i agentów, które potrzebują tokenów dostawców w czasie działania. Podaje też daty: do 30 listopada 2026 dostawcy z Marketplace, którzy nie obsługują OIDC od Vercel i wciąż polegają na długoterminowych sekretach, dostaną etykietę „Not secure”, a w styczniu 2027 te bez bezpiecznego uwierzytelniania znikną z katalogu. Nasze zdanie: termin dotyczy dostawców, ale spada na Twoje projekty. Spisz już teraz integracje, z których korzystasz, i klucze chmurowe w zmiennych środowiskowych; wszystko, co przyjmie token OIDC z Vercel, powinno go dostać, bo klucz, który nie opuszcza platformy, nie wycieknie przez log, repozytorium ani kontekst agenta. ### Jak Vercel Agent bezpiecznie dostaje się do produkcji 23 października 2026 Tom Dale opisał, [jak Vercel Agent uzyskuje dostęp do produkcji](https://vercel.com/blog/how-vercel-agent-accesses-production-safely). Każdy zakres `read:` należy do bazowego zestawu, z którego agent korzysta bez pytania; wszystko ponad to, na przykład `read-write:deployment` przy ponownym wdrożeniu albo otwarcie pull requesta na GitHubie, trafia do planu, który użytkownik zatwierdza w całości. Agent działa jako Vercel App, więc jego dostęp nigdy nie przekroczy roli zatwierdzającego. Tokeny z usługi OAuth Vercel są krótkotrwałe i mają zakresy, a API odrzuca żądanie spoza nich nawet wtedy, gdy model uważa je za potrzebne. Plany są sprawdzane względem tego samego rejestru zakresów, którego używa usługa OAuth, a przed wznowieniem planu środowisko sprawdza, czy plan jest nadal aktywny, więc zatrzymany plan nie zadziała na tokenie, który jeszcze nie wygasł. Nasze zdanie: to wzorzec do skopiowania, jeśli dajesz własnemu agentowi dostęp do produkcji. Czytanie swobodnie, zapis tylko po zatwierdzonym planie, limit na uprawnieniach użytkownika i egzekwowanie zakresów w API, a nie w prompcie. Sam tekst zauważa, że dostęp tylko do odczytu też może ujawnić konfigurację, a logi budowania mogą zawierać złośliwe instrukcje. ### Zgłoszenia prosto z Vercel MCP Od 23 października 2026 [serwer Vercel MCP ma narzędzie `submit_feedback`](https://vercel.com/changelog/send-feedback-from-vercel-mcp): poproś agenta o zgłoszenie błędu, utrudnienia albo prośby o funkcję, a może dołączyć zadanie, oczekiwany wynik, faktyczny wynik i rodzaj zgłoszenia. Narzędzie wymaga zalogowania i wysyła coś tylko na Twoją prośbę. Nasze zdanie: drobiazg, ale przydatny jest kontekst. Kiedy `deploy_to_vercel` zawiedzie w sesji agenta, agent może złożyć zgłoszenie z dokładnym krokiem, który się wysypał, póki jeszcze go pamięta, zamiast żebyś odtwarzał go w formularzu wsparcia. ## Claude ### Anthropic przekazuje Agent Skills fundacji Agentic AI Foundation 22 października 2026 Anthropic [przekazał standard Agent Skills fundacji Agentic AI Foundation](https://www.anthropic.com/news/donating-agent-skills-to-the-agentic-ai-foundation) (AAIF), projektowi Linux Foundation, który współzałożył z Block i OpenAI i w którym jest już Model Context Protocol. Darowizna obejmuje standard, jego nazwę i logo, [organizację agentskills na GitHubie](https://github.com/agentskills/agentskills) i domenę agentskills.io. Utrzymują go jako osoby prywatne inżynierowie z Anthropic, Google, OpenAI i innych firm, a głównymi opiekunami są David Soria Parra i Mahesh Murag; proponowany plan to wersjonowane wydania, formalny proces propozycji i wytyczne bezpieczeństwa dla tych, którzy piszą i instalują skille. Anthropic liczy ponad 70 platform agentowych obsługujących Skills, milion opublikowanych skilli i blisko 280 milionów instalacji. Nasze zdanie: dziś nie trzeba niczego zmieniać; ogłoszenie zmienia to, kto zarządza standardem, a nie format Twoich skilli. Zmienia się to, że format nie należy już do jednego dostawcy, więc skill staje się rozsądnym sposobem, by przekazać konwencje zespołu każdemu agentowi, którego używacie. Zanim zaczniesz instalować skille od obcych, poczekaj na pierwsze wersjonowane wydanie i jego wytyczne bezpieczeństwa. ### Claude API w wersji 2026-10-21 i dwie mniejsze zmiany platformy [Informacje o wydaniach Claude](https://platform.claude.com/docs/en/release-notes/overview) z 21 października 2026 ogłaszają wersję API `2026-10-21` i nowe SDK, które domyślnie ją wysyłają (TypeScript 1.0.0, Python 2.0.0, Go 2.0.0, Java 3.0.0, C# 13.0.0, PHP 1.0.0, Ruby 2.0.0 i CLI `ant` 2.0.0), z licencją zmienioną z MIT na Apache 2.0. Tego samego dnia [profile użytkowników](https://platform.claude.com/docs/en/manage-claude/user-profiles) dostały pola `enforcement_status` i `enforcement_actions`, które pokazują, czy Anthropic ograniczył albo zablokował któregoś z Twoich klientów końcowych, a lista profili przyjmuje filtr `enforcement_status[]`. 22 października Anthropic uruchomił [Claude Models on Google Cloud (Anthropic managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed): Claude API prowadzone przez Anthropic, dostępne przez projekt w Google Cloud, z dostępem przez Google Cloud IAM i rozliczeniem przez Google Cloud Marketplace; działa tam też fast mode dla Claude Opus 5.5. Nasze zdanie: nie pozwól, by bot od zależności przeniósł Cię na nową główną wersję SDK bez przeglądu; nasz [przewodnik po migracji na wersję API 2026-10-21](https://www.outofplace.space/pl/blog/anthropic-sdk-migracja-api-2026-10-21#jak-zaktualizowac-anthropic-sdk-do-wersji-api-2026-10-21) wymienia, co się psuje i w jakiej kolejności to naprawiać. Jeśli odsprzedajesz Claude własnym użytkownikom, odpytuj filtr blokad, żeby zablokowane konto pojawiło się w Twoim panelu administracyjnym, zanim pojawi się jako nieudane żądania. ## Dalsza lektura - [Wydanie Next.js 16.4.3](https://github.com/vercel/next.js/releases/tag/v16.4.3): Osiem przeniesionych zmian z 23 października 2026, z linkami do każdego pull requesta. - [Vercel: Death to long-lived static credentials](https://vercel.com/blog/death-to-long-lived-static-credentials): OIDC na Vercel dziś i terminy dla Marketplace: 30 listopada 2026 i styczeń 2027. - [Anthropic: Donating Agent Skills to the Agentic AI Foundation](https://www.anthropic.com/news/donating-agent-skills-to-the-agentic-ai-foundation): Co przekazano, kto utrzymuje standard i jaki jest proponowany plan. --- # Anthropic SDK i nowa wersja API: co psuje i co zmienić (PL) Source: https://www.outofplace.space/pl/blog/anthropic-sdk-migracja-api-2026-10-21 · Published 2026-10-24 Category: Web development · Tags: Claude, TypeScript, Python > Anthropic TypeScript SDK 1.0.0 i Python SDK 2.0.0 wysyłają wersję API 2026-10-21: temperature daje błąd 400, a klucz idzie jako Bearer. Co poprawić najpierw. 21 października 2026 Anthropic wydał wersję Claude API `2026-10-21` i nową główną wersję każdego SDK, które wysyła ją domyślnie: TypeScript SDK 1.0.0, Python SDK 2.0.0, pięć innych SDK i CLI `ant`. Aktualizacja psuje dwie rzeczy naraz. Wersja API odrzuca `temperature`, `top_p` i `top_k` błędem 400, nawet przy wartościach domyślnych, a także bloki document w wiadomościach asystenta i cytowania w wiadomościach użytkownika. SDK wysyłają klucz API jako `Authorization: Bearer` zamiast `X-Api-Key`, co psuje każde proxy, bramkę czy zaślepkę w testach, które czytają stary nagłówek. To zmień najpierw: usuń trzy parametry losowania, potem przestaw wszystko, co czyta `X-Api-Key`, na `Authorization`. Stare główne wersje SDK dalej wysyłają `2023-06-01`, która działa i nie ma ogłoszonej daty końca, więc nic się nie psuje, dopóki nie zaktualizujesz. Każde twierdzenie poniżej sprawdziliśmy 24 października 2026 w [przewodniku migracji](https://platform.claude.com/docs/en/api/migration-2026-10-21), informacjach o wydaniach, na GitHubie oraz w rejestrach npm i PyPI; nowych SDK nie uruchamialiśmy na API. - TypeScript SDK 1.0.0 i Python SDK 2.0.0 opublikowano 21 października 2026; 24 października najnowsze są 1.3.0 i 2.3.0. - Wersja API `2026-10-21` zwraca 400 dla `temperature`, `top_p` i `top_k`, przy każdej wartości i na każdym modelu. - SDK wysyłają klucz API jako `Authorization: Bearer`; klient trzyma teraz dokładnie jedno poświadczenie. - Na Amazon Bedrock `2026-10-21` działa tylko z modelami Claude 4.7 i nowszymi, więc starsze modele na Bedrocku zostają na starym SDK. - Nowe wersje główne mają licencję Apache 2.0 zamiast MIT. ## Co się zmieniło 21 października 2026 [Informacje o wydaniach z 21 października 2026](https://platform.claude.com/docs/en/release-notes/overview) wymieniają osiem nowych wersji, które domyślnie wysyłają `2026-10-21`, wszystkie na licencji Apache 2.0, gdzie wcześniejsze były na MIT: | SDK lub narzędzie | Pakiet | Pierwsza wersja na `2026-10-21` | | ----------------- | -------------------------------------- | ------------------------------: | | TypeScript | `@anthropic-ai/sdk` | 1.0.0 | | Python | `anthropic` | 2.0.0 | | Go | `github.com/anthropics/anthropic-sdk-go/v2` | 2.0.0 | | Java | `com.anthropic:anthropic-java` | 3.0.0 | | C# | `Anthropic` | 13.0.0 | | PHP | `anthropic-ai/sdk` | 1.0.0 | | Ruby | gem `anthropic` | 2.0.0 | | CLI | `ant` | 2.0.0 | W tych samych informacjach o wydaniach 15 października tryb fast dla Claude Opus 5.5 wyszedł z wersji testowej, co opisaliśmy w [przeglądzie nowości web dev z 18 października](https://www.outofplace.space/pl/blog/nowosci-web-dev-2026-10-18); to wydanie wymaga więcej od twojego kodu. Dla dwóch SDK, których używa większość zespołów webowych, rejestry podają dokładny czas. [Dokument rejestru npm](https://registry.npmjs.org/@anthropic-ai/sdk) podaje czas publikacji i licencję każdej wersji; API JSON w PyPI podaje czasy wysłania [wszystkich wydań](https://pypi.org/pypi/anthropic/json) i licencję wersji [1.17.0](https://pypi.org/pypi/anthropic/1.17.0/json) i [2.0.0](https://pypi.org/pypi/anthropic/2.0.0/json). Oto ostatnia wersja na starej wersji API, pierwsza nowa główna i wersja aktualna 24 października 2026: | Pakiet | Ostatnia na `2023-06-01` | Pierwsza na `2026-10-21` | Najnowsza 24.10.2026 | | ------------------- | ------------------------ | ------------------------ | -------------------- | | `@anthropic-ai/sdk` | 0.137.0, 20.10, MIT | 1.0.0, 21.10, 16:00 UTC | 1.3.0, 23.10 | | `anthropic` (PyPI) | 1.17.0, 20.10, MIT | 2.0.0, 21.10, 15:51 UTC | 2.3.0, 23.10 | Wydania na GitHubie ([TypeScript sdk-v1.0.0](https://github.com/anthropics/anthropic-sdk-typescript/releases/tag/sdk-v1.0.0), [Python v2.0.0](https://github.com/anthropics/anthropic-sdk-python/releases/tag/v2.0.0)) wymieniają jedną zmianę łamiącą zgodność: „add support for new API version 2026-10-21”. Co to oznacza w praktyce, mówi przewodnik migracji, w dwóch grupach. ### Co odrzuca nowa wersja API Dotyczy to `POST /v1/messages`, liczenia tokenów i każdego żądania w Message Batch utworzonym z `2026-10-21`, według sekcji [breaking changes](https://platform.claude.com/docs/en/api/migration-2026-10-21#breaking-changes): | Żądanie | `2023-06-01` | `2026-10-21` | | ------------------------------------------------------------ | ------------ | ----------------------------------------------------- | | `temperature`, `top_p` lub `top_k`, dowolna wartość | Przyjęte | Błąd 400 | | Blok `document` bezpośrednio w wiadomości `assistant` | Przyjęte | Błąd 400; dokumenty wysyłaj w wiadomościach `user` | | Blok `text` z niepustym `citations` w wiadomości `user` | Przyjęte | Błąd 400, także wewnątrz bloków `search_result` | Dwie rzeczy dalej przechodzą: cytowania na blokach tekstu w wiadomościach asystenta (wcześniejsze odpowiedzi Claude’a, które odsyłasz) i ustawienie `"citations": {"enabled": true}` na dokumentach i wynikach wyszukiwania. Dokument zagnieżdżony w innym bloku, np. w wyniku web fetch zwróconym przez Claude’a, też jest w porządku. Najważniejsza jest zmiana parametrów losowania. [Strona wersji](https://platform.claude.com/docs/en/api/versioning) mówi, że błąd 400 przychodzi „on every model”. Na modelach Claude 4.7 i nowszych, które i tak przyjmują tylko wartości domyślne, usunięcie parametrów niczego nie zmienia. Na modelu, który przyjmuje inne wartości, np. Claude Sonnet 4.6, żądanie z niską `temperature` dla bardziej powtarzalnych odpowiedzi traci ten efekt, a przewodnik mówi, że żadne inne ustawienie go nie zastępuje. Admin API i Claude Enterprise Analytics API też tracą stare nazwy pól: `roles` zmienia się w `role_ids`, `group_id` w `rbac_group_id`, `name` w rolach RBAC w `display_name`, `group_type` w `group.type`, `actor.email` w `actor.email_address`, a `summaries` w `data`. Klucze API tracą `workspace_id` na rzecz `scope`, które ma inne wartości: klucz przypisany do Default Workspace niesie teraz prawdziwe ID tej przestrzeni, gdzie wcześniej było `null`. ### Co SDK zmieniają same z siebie [Zmiany w SDK i CLI](https://platform.claude.com/docs/en/api/migration-2026-10-21#sdk-changes) nie zależą od wersji API. TypeScript i Python obok siebie: | Zmiana | TypeScript 1.0.0 | Python 2.0.0 | | ----------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | | Nagłówek klucza API | `Authorization: Bearer`, z `apiKey` i `ANTHROPIC_API_KEY` | `Authorization: Bearer`, z `api_key` i `ANTHROPIC_API_KEY` | | Dwa poświadczenia w jednym kliencie | Rzuca `TypeError` | Rzuca `ValueError` | | `MessageParam` | Unia `UserMessageParam`, `AssistantMessageParam`, `SystemMessageParam`; tylko typy | Ta sama unia; wywołanie lub dziedziczenie `MessageParam` rzuca `TypeError` | | `betas` w `models.list`/`retrieve` | Usunięte z typów parametrów; użyj `client.beta.models` | Przekazanie to `TypeError`; użyj `client.beta.models` | | `compactionControl` w tool runnerze | Usunięte (przestało działać w 0.129.0); użyj kompakcji po stronie serwera | Nie wymieniono | | Text Completions | Usunięte | Nie wymieniono | | Pakiety platform | Pakiety Bedrock, Vertex, Foundry, AWS i Google Cloud potrzebują własnego 1.0.0 | Nie wymieniono | | Licencja | Apache-2.0 (0.137.0 było na MIT) | Apache-2.0 (1.17.0 było na MIT) | Zmiana nagłówka najczęściej zepsuje coś poza twoim kodem. Wszystko między aplikacją a API, co czyta `X-Api-Key`, przestaje widzieć klucz: firmowe proxy, bramka API, middleware, które go sprawdza, filtr logów, który go maskuje, zaślepka w teście, która go oczekuje. Samo API przyjmuje klucz w obu nagłówkach, jak podaje przewodnik migracji. Nie każdy klient się zmienia: w TypeScripcie `apiKey` w `@anthropic-ai/foundry-sdk` dalej idzie jako `X-Api-Key`, a `apiKey` w `@anthropic-ai/bedrock-sdk` już wcześniej był tokenem Bearer; w Pythonie `AnthropicFoundry` dalej wysyła `x-api-key`, a `AnthropicBedrockMantle` już wcześniej wysyłał token Bearer. Zasada jednego poświadczenia łapie konfiguracje, które wysyłały razem token bramki i klucz API. Gdy w kodzie nie podasz żadnego, a ustawione są i `ANTHROPIC_API_KEY`, i `ANTHROPIC_AUTH_TOKEN`, klient użyje klucza i raz zapisze ostrzeżenie. ## Kogo to dotyczy i jak to sprawdzić Dotyczy cię od dnia, w którym zainstalujesz nową wersję główną, nie wcześniej. Przeszukanie repozytorium pokaże, ile jest pracy: | Szukaj w kodzie i konfiguracji | Jeśli znajdziesz | | ---------------------------------------------------- | ----------------------------------------------------------------------------- | | `temperature`, `top_p`, `top_k` w wywołaniach Messages | Usuń je albo zostaw to żądanie na starym SDK | | `X-Api-Key` (dowolna wielkość liter) w proxy, middleware, mockach | Czytaj `Authorization` albo sam wysyłaj `X-Api-Key` | | `apiKey` i `authToken` (lub `api_key` i `auth_token`) w jednym kliencie | Podaj jedno; drugie rzuci błąd | | `models.list(` lub `models.retrieve(` z `betas` | Wołaj `client.beta.models` | | `MessageParam(` (Python) lub `extends MessageParam` (TypeScript) | Napisz literał słownika albo alias typu z `&` | | `compactionControl` (TypeScript) | Przejdź na `context_management` z `compact_20260112` | | Bedrock z Claude Opus 4.6 lub starszym | Zostań przy obecnym SDK, dopóki nie przejdziesz na model 4.7 lub nowszy | | `ant --api-key` lub `ant --auth-token` w skryptach i CI | `ant` 2.0.0 usuwa obie flagi: użyj `ANTHROPIC_API_KEY`, `--api-key-stdin` albo `ant auth login` (dla tokena `ANTHROPIC_AUTH_TOKEN` lub `--auth-token-stdin`) | Wiersz o Bedrocku wymaga uwagi. Nowe SDK wysyłają `2026-10-21` także z klientów Amazon Bedrock i Google Cloud, a na Bedrocku ta wersja istnieje tylko dla modeli Claude 4.7 i nowszych. Jeśli wołasz tam starszy model, [krok aktualizacji](https://platform.claude.com/docs/en/api/migration-2026-10-21#upgrade) każe zostać przy obecnej wersji SDK. W TypeScripcie to wstrzymuje całe drzewo zależności: według [rejestru npm](https://registry.npmjs.org/@anthropic-ai/bedrock-sdk) `@anthropic-ai/bedrock-sdk` 1.0.0 wymaga `@anthropic-ai/sdk` `>=1.0.0 <2`, a 0.36.0 wymaga `>=0.115.1 <1`. Strona wersji wymienia też `2026-10-21` na Claude Platform on AWS, w obu ofertach Google Cloud i w Microsoft Foundry, a ograniczenie modeli podaje tylko dla Bedrocka. ## Jak zaktualizować Anthropic SDK do wersji API 2026-10-21 **1. Przypnij ostatnią starą wersję i zapisz punkt odniesienia.** Zanotuj, czego używasz dziś (np. `@anthropic-ai/sdk` 0.137.0 albo `anthropic` 1.17.0), i uruchom na tym testy, żeby odróżnić błąd migracji od starego i móc wrócić do znanej wersji. **2. Usuń temperature, top_p i top_k.** Wykreśl te trzy parametry z każdego żądania Messages i Batch. Dla żądania, które zależy od niskiej temperatury na modelu, który ją przyjmuje, zdecyduj teraz: zaakceptuj wartość domyślną albo zostaw tę ścieżkę na starym SDK na jakiś czas. **3. Przestaw wszystko, co czyta X-Api-Key, na Authorization.** Zaktualizuj proxy, bramki, middleware, maskowanie logów i zaślepki w testach, by czytały `Authorization: Bearer `. Jeśli bramki nie da się jeszcze zmienić, ustaw nagłówek sam: w TypeScripcie `defaultHeaders: { "X-Api-Key": apiKey, Authorization: null }`, w Pythonie funkcją `auth` na kliencie HTTP, którą pokazuje przewodnik. **4. Zainstaluj najnowszą nową wersję główną razem z pakietami platform.** Zainstaluj `@anthropic-ai/sdk@^1` (1.3.0 na 24 października) albo `anthropic>=2,<3` (2.3.0), a nie dokładnie 1.0.0 czy 2.0.0: wersje 1.2.0 i 2.2.0 poprawiły tool runner. W TypeScripcie przenieś `@anthropic-ai/bedrock-sdk`, `vertex-sdk`, `foundry-sdk`, `aws-sdk` czy `google-cloud-sdk` na 1.x w tej samej zmianie, inaczej menedżer pakietów zainstaluje dla nich drugą, starszą kopię SDK. **5. Popraw to, co zgłoszą kompilator i testy.** Podawaj jedno poświadczenie na klienta, przenieś wywołania z `betas` do `client.beta.models`, przepisz konstruktory i interfejsy `MessageParam`, usuń bloki `document` z wiadomości asystenta i `citations` z wiadomości użytkownika. Potem puść testy na `2026-10-21`, z jednym prawdziwym żądaniem na każdą ścieżkę kodu, zanim wydasz zmianę. W TypeScripcie dwie zmiany, których potrzebuje większość aplikacji, wyglądają tak (druga to przykład z przewodnika migracji): ```ts title="migrate.ts" // 0.x: przyjmowane na 2023-06-01 await client.messages.create({ model, max_tokens: 1024, temperature: 0.2, messages }); // 1.x: temperature nie ma już w typach, a API zwraca dla niego 400 await client.messages.create({ model, max_tokens: 1024, messages }); // 0.x const page = await client.models.list({ betas: [beta] }); // 1.x const page = await client.beta.models.list({ betas: [beta] }); ``` ## Na co uważać - **Brak daty końca `2023-06-01`.** Na 24 października 2026 nie podają jej ani informacje o wydaniach, ani strona wersji, a strona wersji zaleca najnowszą wersję, kiedy tylko to możliwe. Pozostanie przy starej wersji głównej traktuj jako decyzję z datą przeglądu, nie jako plan. - **Nic nie zastępuje niskiej temperatury.** Przewodnik daje tylko dwie opcje: przestać ją wysyłać albo zostawić to żądanie na `2023-06-01`. Jeśli liczy się powtarzalność odpowiedzi, napisz ewaluację, zanim przełączysz model, który respektował twoją temperaturę. - **Brak opisanego tekstu błędu.** Przewodnik mówi, że te żądania zwracają 400, ale nie cytuje komunikatu. [Strona błędów](https://platform.claude.com/docs/en/api/errors) przypisuje 400 do `invalid_request_error`, a SDK rzucają dla niego wyjątek o konkretnym typie, więc test sprawdzający status lub typ jest pewniejszy niż porównywanie tekstu. - **Poprawki tool runnera po 1.0.0.** [TypeScript 1.2.0](https://github.com/anthropics/anthropic-sdk-typescript/releases/tag/sdk-v1.2.0) i [Python 2.2.0](https://github.com/anthropics/anthropic-sdk-python/releases/tag/v2.2.0), oba z 23 października, poprawiają tool runner: wydanie TypeScript wokół `setMessagesParams()` i `pushMessages()`, wydanie Python wokół `append_messages()` i `set_messages_params()`. Zaczynaj od najnowszej wersji. - **Biblioteki zbudowane na SDK.** Framework, który opakowuje `@anthropic-ai/sdk` albo `anthropic`, deklaruje własny zakres wersji i własne typy. Sprawdź, czy obsługuje nową wersję główną, zanim zaktualizujesz; przewodnik migracji obejmuje tylko pakiety Anthropic. - **Ewidencja licencji.** Apache 2.0 nie wymaga zmian w kodzie, ale jeśli śledzisz licencje zależności, zaktualizuj wpis. Wszystkie źródła czytaliśmy 24 października 2026; zanim zaplanujesz aktualizację, sprawdź w informacjach o wydaniach, czy nie doszło coś nowego. Wcześniejsze nowości wokół Claude’a, w tym wyjście trybu fast dla Opus 5.5 z wersji testowej, są w podlinkowanym wyżej przeglądzie web dev z 18 października. ## Dalsza lektura - [Migrating to API version 2026-10-21](https://platform.claude.com/docs/en/api/migration-2026-10-21): Każda zmiana łamiąca zgodność z kodem przed i po, dla wszystkich ośmiu SDK i CLI. - [Claude API: wersje](https://platform.claude.com/docs/en/api/versioning): Co zmieniała każda wersja API i gdzie jest dostępna 2026-10-21, łącznie z Bedrockiem. - [Informacje o wydaniach Claude Platform](https://platform.claude.com/docs/en/release-notes/overview): Wpis z 21 października 2026 z ośmioma wersjami SDK i CLI oraz zmianą licencji. - [anthropic-sdk-typescript sdk-v1.0.0](https://github.com/anthropics/anthropic-sdk-typescript/releases/tag/sdk-v1.0.0): Wydanie TypeScript na GitHubie; kolejne wydania 1.x są obok. - [anthropic-sdk-python v2.0.0](https://github.com/anthropics/anthropic-sdk-python/releases/tag/v2.0.0): Wydanie Python na GitHubie, a po nim 2.1.0 do 2.3.0. - [@anthropic-ai/sdk w rejestrze npm](https://registry.npmjs.org/@anthropic-ai/sdk): Każda wersja z czasem publikacji i licencją. --- # React Server Components: co trafia do przeglądarki (PL) Source: https://www.outofplace.space/pl/blog/react-server-components-co-trafia-do-przegladarki · Published 2026-10-23 Category: Next.js i React · Tags: React, Next.js > React Server Components w Next.js 16 na żywym demo: co zostaje na serwerze, co trafia do przeglądarki jako JavaScript, a co niesie HTML i payload RSC. React Server Components (komponenty serwerowe) to komponenty, których kod działa tylko na serwerze. W App Routerze Next.js każda strona i każdy layout jest nim domyślnie, a przeglądarka dostaje to, co wyrenderowały, jako HTML i drugi raz w payloadzie RSC, nigdy ich kod. Jako JavaScript trafia do niej tylko plik zaczynający się od `"use client"` i wszystko, co on importuje. Takie Client Components i tak są najpierw renderowane do HTML na serwerze, a potem hydratowane w przeglądarce. Dane przechodzą z serwera do klienta tylko przez serializowalne propsy, a Server Component przekazany jako `children` zostaje wynikiem z serwera nawet wewnątrz Client Component. Wszystko to pokazuje jedno demo na Next.js 16.4.0 z React 19.3.0, a dziewięć testów w Playwright sprawdza zachowanie demo opisane w tym tekście. We własnej aplikacji używaj wersji z poprawkami: [poprawki RCE w React i Next.js z października 2026](https://www.outofplace.space/pl/blog/nowosci-web-dev-2026-10-18) dotyczą tej samej warstwy. Demo na żywo: https://lab.outofplace.space/demos/react-server-components-explained (Next.js 16.4.0; kod z commita b5049c6: https://github.com/outof-place/outofplace-lab/tree/b5049c6980621147d3446a5748a1c6f1d74d4cbc/app/demos/react-server-components-explained) ## Czym są React Server Components? Dokumentacja Reacta opisuje [Server Components](https://react.dev/reference/rsc/server-components) jako komponenty, które renderują się z wyprzedzeniem, „in an environment separate from your client app or SSR server”, czyli w środowisku oddzielonym od aplikacji w przeglądarce i od serwera SSR. W Next.js tym środowiskiem jest serwer, w czasie builda albo przy żądaniu. Komponentu nie oznacza się jako serwerowego: [Server Components nie mają dyrektywy](https://react.dev/reference/rsc/server-components#there-is-no-directive-for-server-components), a `"use server"` oznacza Server Functions. Oznaczasz drugą stronę, przez `"use client"`. Przewodnik Next.js po [granicy między serwerem a klientem](https://nextjs.org/docs/app/guides/server-and-client-boundary#rendering-environments) ujmuje różnicę w jednej tabeli. Tu z tym, co z niej wynika przy pisaniu kodu: | | Server Component | Client Component | | --- | --- | --- | | Oznaczenie | brak (domyślne w `app/`) | `"use client"` na początku pliku | | Renderuje się na serwerze | tak | tak, do HTML | | Działa w przeglądarce | nie | tak, tam się hydratuje | | Jego kod i importy trafiają do JavaScriptu | nie | tak | | `useState`, `useEffect`, `onClick` | nie | tak | | Może czytać sekrety, pliki, bazę danych | tak | nie: traktuj go jak kod przeglądarki | ## Co trafia do przeglądarki: HTML, payload RSC i JavaScript klienta Przy [pierwszym wczytaniu strony w Next.js](https://nextjs.org/docs/app/getting-started/server-and-client-components#on-the-client-first-load) dokumentacja wymienia trzy rzeczy, z których korzysta przeglądarka: HTML do szybkiego, nieinteraktywnego podglądu, payload RSC do uzgodnienia drzew serwera i klienta oraz JavaScript do hydratacji Client Components. Payload RSC to zwarta, zserializowana postać wyrenderowanego drzewa Server Components. Zawiera ich wynik, miejsca na Client Components z odwołaniami do ich plików JavaScript i wszystkie propsy, które Server Component przekazał do Client Component. Server Component w demo podpisuje czas żądania kluczem HMAC. Klucz i moduł `crypto` z Node siedzą w osobnym pliku, który zaczyna się od `import "server-only"`: app/demos/react-server-components-explained/signing.ts (https://github.com/outof-place/outofplace-lab/blob/b5049c6980621147d3446a5748a1c6f1d74d4cbc/app/demos/react-server-components-explained/signing.ts) ```ts import "server-only"; import { createHmac } from "node:crypto"; // A made-up key, public in this repo. In an app it comes from process.env. Either way it lives // only in the server module graph: import "server-only" turns an import from a "use client" // file into a build error. const SIGNING_KEY = "lab-demo-key-stays-on-the-server"; /** The first 12 hex characters of an HMAC-SHA256 of `value`, made with Node's crypto module. */ export function sign(value: string): string { return createHmac("sha256", SIGNING_KEY).update(value).digest("hex").slice(0, 12); } ``` Karta, która z niego korzysta, to funkcja asynchroniczna bez dyrektywy: app/demos/react-server-components-explained/server-card.tsx (https://github.com/outof-place/outofplace-lab/blob/b5049c6980621147d3446a5748a1c6f1d74d4cbc/app/demos/react-server-components-explained/server-card.tsx) ```tsx import { io } from "next/cache"; import { sign } from "./signing"; import styles from "./rsc.module.css"; // Server Components: no directive, so they stay in the server module graph. The browser // receives what they render (as HTML and in the RSC payload), never this code. const renderedOn = () => (typeof window === "undefined" ? "server" : "browser"); export async function ServerCard() { // With Cache Components on, io() keeps what follows out of the build's static shell, // so the server signs a fresh time on every request. await io(); const signedAt = new Date().toISOString(); return (

Server Component

Rendered on
{renderedOn()}
Signed at
Signature
{sign(signedAt)}
); } // Passed to the Client Component as children: it renders here, on the server, and the // Client Component only places its output. export function ServerNote() { return {renderedOn()}, passed in as children; } ``` Testy sprawdzają na buildzie produkcyjnym, co naprawdę dociera: - Odpowiedź HTML ma podpis w znacznikach i ten sam podpis drugi raz w skrypcie ` ``` Jeśli szablon platformy zgody w Tag Managerze już ustawia wartości domyślne, nie dodawaj drugiego wywołania na stronie. **4. Sprawdź to w przeglądarce.** Otwórz stronę w oknie prywatnym i wpisz `dataLayer` w konsoli narzędzi deweloperskich: wpis `consent`, `default` powinien być przed każdym `config` i `event`. Zaakceptuj baner i sprawdź, czy pojawia się wpis `consent`, `update`. **5. Sprawdź dane terenowe.** Wyszukaj swoją stronę w [PageSpeed Insights](https://pagespeed.web.dev/): jeśli ma dość ruchu z Chrome'a, góra raportu pokazuje te same dane CrUX co w tym badaniu. Zmianę widać w pełni po czterech tygodniach, bo CrUX obejmuje kroczące 28 dni. ## Jak mierzyliśmy Strony główne pochodzą z naszego spisu z 24 września 2026, wykonanego przez `OutofplaceResearchBot` (zobacz, [co pobiera nasz crawler i jak go zablokować](https://www.outofplace.space/pl/bot)), który najpierw czyta robots.txt i pobiera tylko stronę główną: 8023 z 9208 domen .pl z listy Tranco odpowiedziało kodem HTML, a po połączeniu domen przekierowujących pod ten sam adres zostało 7785 różnych witryn. Czytaliśmy kod HTML każdej strony głównej bez uruchamiania go i porównywaliśmy go z regułami dla 36 narzędzi zgody, zbudowanymi z każdego hosta skryptów, folderu wtyczki, modułu sklepu i znacznika w kodzie, który dotyczy cookies lub zgody i występuje na co najmniej dwóch stronach głównych. Reguła trafia w to, co ładuje albo rysuje narzędzie: skrypt z hosta dostawcy, folder wtyczki w adresie zasobu, znaczniki, które pisze tylko to narzędzie, albo jego wywołanie konfiguracyjne. Gdy dwie reguły opisują jeden baner, wygrywa jedna: wtyczka WordPressa połączona z serwerami dostawcy liczy się jako platforma u dostawcy, a sklep, który dodał platformę zgody, jako ta platforma, nie wbudowany baner. Sklep na Shoperze liczy się tylko wtedy, gdy ma baner włączony. Domyślne wartości Consent Mode liczą się, gdy kod HTML zawiera wywołanie `consent`, `default`. Dane o szybkości pochodzą od Google. 25 września 2026 zapytaliśmy [API Chrome UX Report](https://developer.chrome.com/docs/crux/api) o adres każdej strony głównej na telefonach, a gdy adres nie miał danych, sprawdziliśmy wersję z www albo bez. CrUX zbiera wczytania stron przez użytkowników Chrome'a na Androidzie i komputerach, którzy udostępniają statystyki użycia, ze wszystkich stron witryny, z 28 dni. Witryna przechodzi CLS przy 75. percentylu 0,1 lub mniej, LCP przy 2,5 s, a INP przy 200 ms. Porównanie (każdy rodzaj narzędzia i każde narzędzie na co najmniej 30 witrynach z danymi CrUX wobec witryn bez wykrytego narzędzia) ustaliliśmy, zanim odczytaliśmy dane terenowe; sklepy rozpoznaje klasyfikator z naszego badania e-commerce. Dla 10 najczęstszych narzędzi wylosowaliśmy po 4 wykrycia, w stałej losowej kolejności, i przeczytaliśmy kod HTML za każdym z nich. Poprawnych było 39 z 40. Jedyny błąd to tag Cookiebota, którego atrybut type ma cudzysłów drukarski, więc przeglądarka nigdy go nie uruchamia. Dwie reguły nie przeszły wcześniejszej rundy tego samego sprawdzenia i zostały zawężone: każdy sklep na Shoperze ma w kodzie szablon banera, włączonego czy nie, a niektóre strony używają identyfikatora popularnej wtyczki WordPressa dla własnego banera. Widzieliśmy tylko stronę główną, taką, jaka przyszła w kodzie HTML, i niczego nie uruchamialiśmy. Baner ładowany przez menedżer tagów i baner zbudowany przez samą stronę są niewidoczne, więc każdy udział to wartość minimalna, a platformy sklepów z wbudowanym banerem, który rozpoznajemy, wypadają lepiej niż te bez niego. Nie sprawdzaliśmy, czy baner daje prawdziwy wybór, czy blokuje cookies przed zgodą ani czy jest zgodny z prawem. Strona główna dłuższa niż 1 MiB została w tym miejscu ucięta (331 takich). Dane terenowe obejmują wszystkie strony witryny, nie tylko główną, i tylko witryny z dostatecznym ruchem z Chrome'a: w CrUX jest 89% witryn z narzędziem i 75% witryn bez niego, więc witryny bez narzędzia są średnio mniejsze. ## Dalsza lektura - [Best practices for cookie notices](https://web.dev/articles/cookie-notice-best-practices): Poradnik Google o banerach cookies, które nie szkodzą LCP, CLS ani INP, od zespołu Chrome'a (po angielsku). - [Set up consent mode on websites](https://developers.google.com/tag-platform/security/guides/consent): Dokumentacja Google o Consent Mode: cztery parametry, polecenia default i update oraz ich kolejność (po angielsku). - [Cumulative Layout Shift (CLS)](https://web.dev/articles/cls): Co mierzy CLS i jakie progi przyjmuje Google (po angielsku). - [Skrypty zewnętrzne na polskich stronach: kto co ładuje](https://www.outofplace.space/pl/blog/skrypty-zewnetrzne-na-polskich-stronach): Nasze badanie tych samych stron głównych: jakie skrypty zewnętrzne ładują polskie strony i jak idą w parze z INP. --- # Strony kancelarii prawnych: jak szybkie są najlepsze? (PL) Source: https://www.outofplace.space/pl/blog/strony-kancelarii-prawnych · Published 2026-09-25 Category: Wydajność · Tags: Kancelarie, Core Web Vitals, llms.txt, Polska > Zmierzyliśmy strony 170 kancelarii z rankingów Legal 500 i Chambers. Większość ładuje się szybko, ale mało która mówi Google i AI, że jest kancelarią. Strona internetowa kancelarii prawnej w Polsce jest zwykle szybka dla osób, które ją otwierają. Zmierzyliśmy strony 170 polskich kancelarii, tych z rankingów The Legal 500 i Chambers dla Polski oraz kilku specjalistycznych, i sprawdziliśmy każdą w [Chrome UX Report](https://developer.chrome.com/docs/crux), zapisie Google o tym, jak szybko strony działają u prawdziwych użytkowników Chrome. Spośród tych z wystarczającym ruchem 74% zalicza [Core Web Vitals](https://web.dev/articles/vitals) na telefonach, więcej niż polskie sklepy w [naszym badaniu Core Web Vitals sklepów internetowych](https://www.outofplace.space/pl/blog/core-web-vitals-sklepow-internetowych). Brakuje im nie szybkości, tylko sygnałów, które wyszukiwarki i asystenci AI czytają najpierw. Tylko 12% stron mówi w danych strukturalnych, że należy do kancelarii, a 7,1% opisuje tak swoich prawników. 71% nie wysyła żadnego z sześciu sprawdzanych nagłówków bezpieczeństwa. I żadna nie blokuje botów AI, choć plik `llms.txt` dla nich publikuje mniej niż co dziesiąta. - 74% kancelarii z rankingów, dla których Chrome ma dane, zalicza Core Web Vitals na telefonach; typowa strona pokazuje główną treść po 1,9 s. - Wolne strony są wolne przez serwer: co dziesiąta czekała w naszym teście 1,6 s lub dłużej na pierwszy bajt. - 78% stoi na WordPressie. - Dane strukturalne kancelarii (`LegalService`) ma 12% stron, dane prawników (`Person`) 7,1%. - 71% nie wysyła żadnego nagłówka bezpieczeństwa; żadna nie blokuje botów AI. ## Jak szybkie są strony kancelarii? Chrome zbiera dane tylko dla stron z odpowiednim ruchem: miało je na telefonach 50 ze 170 stron, głównie większych kancelarii. Spośród tych, dla których da się ocenić wszystkie trzy Core Web Vitals, 74% zalicza je na telefonach i 84% na komputerach. Jeśli strona odpada, to na ładowaniu: LCP w 2,5 sekundy mieści 73% stron, a na dotknięcie w czasie reaguje 97%. **Większość kancelarii z rankingów ładuje się na telefonie w 2,5 sekundy** (Largest Contentful Paint na p75 na telefonach, w sekundach, strony kancelarii z danymi Chrome · CrUX, 28 dni do 22 września 2026) | Zakres | stron | | --- | --- | | 0 s–0,5 s | 0 | | 0,5 s–1 s | 5 | | 1 s–1,5 s | 8 | | 1,5 s–2 s | 15 | | 2 s–2,5 s | 8 | | 2,5 s–3 s | 2 | | 3 s–3,5 s | 5 | | 3,5 s–4 s | 5 | | 4 s–4,5 s | 0 | | 4,5 s–5 s | 0 | | 5 s–5,5 s | 0 | | 5,5 s–6 s | 1 | Source: Chrome UX Report (Google); badanie Outofplace, 24 września 2026. Chart: https://www.outofplace.space/data/blog/law-firm-websites-poland/charts/pl/chart-wiekszosc-kancelarii-z-rankingow-laduje-sie-na-telefonie-w-2-5-s.png Data: https://www.outofplace.space/data/blog/law-firm-websites-poland/2026-09-24/distributions.csv Strony bez danych Chrome zmierzyliśmy sami: każdą stronę główną zapytaliśmy trzy razy o pierwszy bajt, czyli chwilę, w której serwer zaczyna odpowiadać. Typowa strona odpowiedziała po 0,7 s, co dziesiąta po 1,6 s lub później, zanim przeglądarka mogła cokolwiek narysować. Tak wygląda strona składana od nowa dla każdego gościa na współdzielonym serwerze; strona z cache w sieci CDN odpowiada w kilkaset milisekund. Stronę główną z cache podawało tylko 11% kancelarii, a za siecią CDN stało 11%. **Co dziesiąta strona kancelarii każe czekać na serwer ponad 1,6 sekundy** (Czas do pierwszego bajtu strony głównej, w sekundach, mediana z trzech zapytań z Polski, wszystkie strony w badaniu · 24 września 2026) | Zakres | stron | | --- | --- | | 0 s–0,2 s | 6 | | 0,2 s–0,4 s | 55 | | 0,4 s–0,6 s | 14 | | 0,6 s–0,8 s | 30 | | 0,8 s–1 s | 12 | | 1 s–1,2 s | 20 | | 1,2 s–1,4 s | 8 | | 1,4 s–1,6 s | 6 | | 1,6 s–1,8 s | 8 | | 1,8 s–2 s | 3 | | 2 s–2,2 s | 2 | | 2,2 s–2,4 s | 2 | | 2,4 s–2,6 s | 0 | | 2,6 s–2,8 s | 1 | | 2,8 s–3 s | 1 | Source: Pomiar Outofplace, 24 września 2026. Chart: https://www.outofplace.space/data/blog/law-firm-websites-poland/charts/pl/chart-co-dziesiata-strona-kancelarii-kaze-czekac-na-serwer-ponad-1-6-s.png Data: https://www.outofplace.space/data/blog/law-firm-websites-poland/2026-09-24/distributions.csv ## Na czym zbudowane są strony kancelarii? Na WordPressie, zdecydowanie: 78% stron, mniej więcej połowa z nich z wtyczką Yoast SEO. Strony pisane od zera są daleko w tyle, a nowoczesne frameworki jak Next.js i kreatory jak Webflow zdarzają się rzadko. **Cztery na pięć stron kancelarii stoją na WordPressie** (Platforma rozpoznana po kodzie strony głównej, nagłówkach i nazwach ciasteczek · 24 września 2026) | Pozycja | WordPress | Własny kod | Next.js | Webflow | Inne | n | | --- | --- | --- | --- | --- | --- | --- | | Strony | 78% | 15% | 2,4% | 2,4% | 2,4% | 170 | Source: Badanie Outofplace, 24 września 2026. Chart: https://www.outofplace.space/data/blog/law-firm-websites-poland/charts/pl/chart-cztery-na-piec-stron-kancelarii-stoja-na-wordpressie.png Data: https://www.outofplace.space/data/blog/law-firm-websites-poland/2026-09-24/platforms.csv Problemem nie jest sam WordPress, tylko to, co się na nim nawarstwia. Typowa strona główna ładuje 22 skrypty. Spośród stron, na których dało się odczytać wersję jQuery, 20% wciąż ładuje wersję starszą niż 3.5, która załatała znane luki XSS; kilka korzysta z tego samego motywu jednej agencji z jQuery 1.8.3 z 2012 roku. ## Czy Google i AI wiedzą, że to kancelaria? Wyszukiwarki i asystenci AI nie muszą zgadywać, czym jest strona, jeśli ona sama to powie. [Dane strukturalne](https://developers.google.com/search/docs/appearance/structured-data/organization) w JSON-LD mówią wprost: to kancelaria, pod tym adresem, z tymi specjalizacjami i tymi prawnikami. Jakieś dane strukturalne ma dwie trzecie stron, ale głównie ogólne `Organization` i okruszki, które wtyczka SEO dodaje sama. Typy opisujące praktykę prawniczą są rzadkie: [`LegalService`](https://schema.org/LegalService) ma 12% stron, `Person` dla prawników 7,1%, `FAQPage` 1,8%. Jedna strona wciąż używa `Attorney`, typu, który schema.org wycofał na rzecz `LegalService`. **Mało która strona opisuje kancelarię i jej prawników w danych strukturalnych** (Odsetek stron, których strona główna zawiera dany typ JSON-LD · 95% przedział · 24 września 2026) | Pozycja | Wartość | Przedział 95% | n | | --- | --- | --- | --- | | Jakikolwiek JSON-LD | 68% | 60%–74% | 170 | | Organization | 54% | 47%–61% | 170 | | BreadcrumbList | 48% | 41%–56% | 170 | | LegalService (kancelaria) | 12% | 8,2%–18% | 170 | | Person (prawnik) | 7,1% | 4,1%–12% | 170 | | FAQPage | 1,8% | 0,6%–5,1% | 170 | | Attorney | 0,6% | 0,1%–3,3% | 170 | Source: Badanie Outofplace, 24 września 2026. Chart: https://www.outofplace.space/data/blog/law-firm-websites-poland/charts/pl/chart-malo-ktora-strona-opisuje-kancelarie-i-jej-prawnikow-w-danych-st.png Data: https://www.outofplace.space/data/blog/law-firm-websites-poland/2026-09-24/flags.csv Podstawy układu strony są słabsze, niż można by się spodziewać po firmach, które sprzedają precyzję. 34% stron głównych nie ma nagłówka `h1`, więc strona nigdzie nie mówi w jednym zdaniu, o czym jest. Spośród stron z wersjami językowymi 30% wskazuje wersję domyślną (`x-default`) dla gości, których języka nie obsługuje. **Co trzecia strona główna kancelarii nie ma głównego nagłówka** (Odsetek stron z daną cechą; x-default wśród stron z wersjami językowymi · 95% przedział · 24 września 2026) | Pozycja | Wartość | Przedział 95% | n | | --- | --- | --- | --- | | Mapa strony w robots.txt | 77% | 70%–83% | 170 | | Dokładnie jeden h1 | 48% | 40%–55% | 170 | | Brak h1 | 34% | 27%–42% | 170 | | hreflang z x-default | 30% | 22%–39% | 111 | | llms.txt | 9,4% | 5,9%–15% | 170 | Source: Badanie Outofplace, 24 września 2026. Chart: https://www.outofplace.space/data/blog/law-firm-websites-poland/charts/pl/chart-co-trzecia-strona-glowna-kancelarii-nie-ma-glownego-naglowka.png Data: https://www.outofplace.space/data/blog/law-firm-websites-poland/2026-09-24/flags.csv ## Czy strony kancelarii są bezpieczne? Nagłówki bezpieczeństwa to kilka linijek konfiguracji serwera, które mówią przeglądarce, jak chronić stronę: [HSTS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Strict-Transport-Security) trzyma ją na HTTPS, [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) ogranicza, jakie skrypty mogą się uruchomić, ochrona przed ramkami nie pozwala innej stronie jej osadzić. Dla kancelarii, do których przez formularz trafiają poufne pierwsze wiadomości, to tanie zabezpieczenie. 71% stron nie wysyła żadnego z sześciu sprawdzanych nagłówków; HSTS wysyła 15%, a Content Security Policy 7,7%. **Siedem na dziesięć stron kancelarii nie wysyła żadnego nagłówka bezpieczeństwa** (Odsetek stron według liczby wysyłanych nagłówków z sześciu sprawdzanych · strony główne, 24 września 2026) | Pozycja | Wartość | | --- | --- | | 0 | 71% | | 1 | 14% | | 2 | 7,1% | | 3 | 1,8% | | 4 | 2,9% | | 5 | 1,8% | Source: Badanie Outofplace, 24 września 2026. Chart: https://www.outofplace.space/data/blog/law-firm-websites-poland/charts/pl/chart-siedem-na-dziesiec-stron-kancelarii-nie-wysyla-zadnego-naglowka.png Data: https://www.outofplace.space/data/blog/law-firm-websites-poland/2026-09-24/distributions.csv **Najczęstszy nagłówek, HSTS, ma co siódma strona** (Odsetek stron, których strona główna wysyła dany nagłówek · 95% przedział · 24 września 2026) | Pozycja | Wartość | Przedział 95% | n | | --- | --- | --- | --- | | Strict-Transport-Security | 15% | 10%–21% | 170 | | Ochrona przed ramkami | 14% | 9,7%–20% | 170 | | X-Content-Type-Options | 13% | 8,7%–19% | 170 | | Referrer-Policy | 10% | 6,3%–15% | 170 | | Permissions-Policy | 8,2% | 5%–13% | 170 | | Content-Security-Policy | 7,7% | 4,5%–13% | 170 | Source: Badanie Outofplace, 24 września 2026. Chart: https://www.outofplace.space/data/blog/law-firm-websites-poland/charts/pl/chart-najczestszy-naglowek-hsts-ma-co-siodma-strona.png Data: https://www.outofplace.space/data/blog/law-firm-websites-poland/2026-09-24/flags.csv ## Jak kancelarie traktują boty AI? Z otwartymi drzwiami. Żadna ze 170 stron nie blokuje bota AI w `robots.txt`, a tylko 5 wymienia któregoś z nazwy, żeby go wpuścić. Tym kancelarie różnią się od najpopularniejszych polskich serwisów, z których co najmniej jednego bota blokuje 21%, jak pokazało nasze badanie [botów AI w polskim internecie](https://www.outofplace.space/pl/blog/boty-ai-polski-internet). 16 stron (9,4%) publikuje [`llms.txt`](https://llmstxt.org/), tekstowy przewodnik po stronie dla modeli językowych. To ma znaczenie, gdy klient pyta asystenta AI zamiast wyszukiwarki. Zadaliśmy czterem asystentom z wyszukiwaniem w sieci (od OpenAI, Google, Perplexity i Anthropic) 51 pytań, jakie mógłby zadać przyszły klient w pięciu dziedzinach, od przestępstw gospodarczych po kontrole celno-skarbowe, po polsku i po angielsku: łącznie 332 odpowiedzi. Odpowiedzi wymieniają kancelarie i podają, skąd o nich wiedzą. Rankingi się liczą: The Legal 500 cytowało 17% odpowiedzi, Chambers 14%. Ale wśród dziesięciu najczęściej cytowanych źródeł 6 to strony samych kancelarii. To, co kancelaria napisze o sobie w formie czytelnej dla maszyn, trafia do odpowiedzi. ## Co poprawić na stronie kancelarii Większość tego, czego w badaniu brakowało, to praca na dni, a nie nowa strona. **1. Podawać strony z cache.** Cache stron (wtyczka do WordPressa albo cache hostingu) i sieć CDN skracają czas do pierwszego bajtu z sekund do kilkuset milisekund. Wynik widać w [PageSpeed Insights](https://pagespeed.web.dev/): na górze raportu dane prawdziwych użytkowników, jeśli jest ich dość. **2. Powiedzieć, że to kancelaria, i kim są prawnicy.** Dodać `LegalService` dla kancelarii i `Person` dla każdego prawnika, powiązane ze sobą, obok tego, co już generuje wtyczka SEO. **3. Wysyłać nagłówki bezpieczeństwa.** Sześć linijek w konfiguracji serwera albo w CDN. Content Security Policy najlepiej zacząć w trybie tylko do raportowania, żeby nic się nie zepsuło, zanim zostanie dostrojona. **4. Dać każdej stronie jeden jasny nagłówek.** Jeden `h1`, który mówi, o czym jest strona, słowami, jakich użyłby klient. **5. Pozwolić asystentom AI się czytać.** Zostawić boty wyszukiwarek wpuszczone w `robots.txt`, opublikować `llms.txt` wskazujący specjalizacje i prawników, a te strony utrzymać czytelne bez skryptów. Minimalny `LegalService` z jednym prawnikiem wygląda tak (dane trzeba zastąpić własnymi): ```json { "@context": "https://schema.org", "@graph": [ { "@type": "LegalService", "@id": "https://www.przyklad-kancelaria.pl/#kancelaria", "name": "Kancelaria Przykład", "url": "https://www.przyklad-kancelaria.pl/", "telephone": "+48 22 000 00 00", "address": { "@type": "PostalAddress", "streetAddress": "ul. Przykładowa 1", "postalCode": "00-001", "addressLocality": "Warszawa", "addressCountry": "PL" }, "knowsAbout": ["Prawo karne gospodarcze", "Kontrole celno-skarbowe"] }, { "@type": "Person", "name": "Anna Przykładowa", "jobTitle": "Adwokat", "worksFor": { "@id": "https://www.przyklad-kancelaria.pl/#kancelaria" } } ] } ``` ## Jak mierzyliśmy Zaczęliśmy od wszystkich kancelarii z rankingów dla Polski w [The Legal 500 EMEA](https://www.legal500.com/c/poland) i Chambers Europe (edycje 2026, publiczne tabele przeczytane 24 września 2026), dodaliśmy szesnaście mniejszych kancelarii od prawa karnego gospodarczego, kontroli celno-skarbowych i obsługi cudzoziemców, a potem ręcznie sprawdziliśmy, że każda strona należy do kancelarii. Kancelarie międzynarodowe, których polskie biuro nie ma własnej strony, pominęliśmy. Z 285 kandydatów zostało 170. OutofplaceResearchBot pobrał najpierw `robots.txt` każdej strony, potem stronę główną z nagłówkami, `llms.txt` i mapę strony, jedno zapytanie naraz. Dane terenowe pochodzą z Chrome UX Report API dla całych domen, 28 dni do 22 września 2026. Odpowiedzi AI przyszły przez Vercel AI Gateway z wyszukiwaniem każdego dostawcy: Gemini i Perplexity odpowiadały na każde pytanie trzy razy, modele OpenAI i Anthropic raz, na próbie pytań ze wszystkich dziedzin. - Chrome ma dane tylko dla stron z odpowiednim ruchem, tu dla 29% z nich; odsetki Core Web Vitals opisują te strony, nie mniejsze kancelarie. - Rankingi faworyzują większe kancelarie. To czołówka rynku, nie każda kancelaria w Polsce. - Czas do pierwszego bajtu mierzyliśmy z jednego miejsca w Polsce, więc służy do porównań między stronami, a nie jako wynik każdego gościa. - Czytaliśmy tylko strony główne; podstrony mogą mieć dane strukturalne, których nie ma strona główna. - Pytania do AI dotyczyły pięciu dziedzin i szły przez API dostawców bez lokalizacji użytkownika, więc aplikacje mogą odpowiadać inaczej, a odpowiedzi zmieniają się z dnia na dzień. - Publikujemy tylko dane zagregowane i nie wymieniamy żadnej kancelarii. ## Dalsza lektura - [Chrome UX Report](https://developer.chrome.com/docs/crux): Dokumentacja Google o danych terenowych, na których opierają się Core Web Vitals. - [schema.org: LegalService](https://schema.org/LegalService): Typ dla praktyki prawniczej, ze wszystkimi właściwościami. - [Content Security Policy (MDN)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP): Jak działa CSP i jak wdrożyć ją najpierw w trybie tylko do raportowania. - [Core Web Vitals sklepów: która platforma jest najszybsza?](https://www.outofplace.space/pl/blog/core-web-vitals-sklepow-internetowych): Core Web Vitals sklepów w danych CrUX: na telefonach zalicza je ponad połowa. Prowadzą Shopify i PrestaShop, Shoper odstaje przez INP. Która platforma wygrywa? - [Boty AI kontra polski internet: robots.txt 1000 stron .pl](https://www.outofplace.space/pl/blog/boty-ai-polski-internet): Sprawdziliśmy plik robots.txt 1000 największych stron .pl: co piąta blokuje boty AI, głównie treningowe jak GPTBot, rzadko wyszukiwarki AI. Jak to rozdzielić? --- # Core Web Vitals sklepów: która platforma jest najszybsza? (PL) Source: https://www.outofplace.space/pl/blog/core-web-vitals-sklepow-internetowych · Published 2026-09-24 Category: Wydajność · Tags: Core Web Vitals, PrestaShop, WooCommerce, Shoper, Shopify > Core Web Vitals sklepów w danych CrUX: na telefonach zalicza je ponad połowa. Prowadzą Shopify i PrestaShop, Shoper odstaje przez INP. Która platforma wygrywa? Sklepy na Shopify i PrestaShop najczęściej zaliczają [Core Web Vitals](https://web.dev/articles/vitals?hl=pl), czyli wskaźniki szybkości Google; sklepy na Shoperze najrzadziej. Wśród domen .pl z [listy popularnych stron Tranco](https://tranco-list.eu/list/Y8YYG/full), tej samej co w [naszym badaniu botów AI na polskich stronach](https://www.outofplace.space/pl/blog/boty-ai-polski-internet), znaleźliśmy 2182 sklepów internetowych i każdy sprawdziliśmy w [Chrome UX Report](https://developer.chrome.com/docs/crux?hl=pl), czyli danych Google o tym, jak szybko strony działają dla prawdziwych użytkowników Chrome. 1975 z nich miało dość ruchu, żeby dało się je zmierzyć na telefonach. Z nich 53% zalicza wszystkie trzy wskaźniki: 63% sklepów na Shopify, 60% na PrestaShop i 33% na Shoperze, którego strony ładują się szybko, ale wolno reagują na dotknięcie. Platforma tłumaczy mniej, niż sugeruje jej wybór. Na większości platform czas ładowania różni się bardziej między sklepami niż między platformami, a każda platforma ma własną słabość: sklepy na WooCommerce tracą na ładowaniu, na Shoperze i we frontach headless na szybkości reakcji, a na komputerach sklepy na IdoSell i Shoperze na przesuwającym się układzie strony. Kto na czym działa: co czwarty sklep stoi na [PrestaShop](https://www.prestashop.com/pl) (25,7%). Platformy open source na własnym serwerze sklepu obsługują ponad połowę z nich, polskie platformy SaaS, takie jak [Shoper](https://www.shoper.pl/) i [IdoSell](https://www.idosell.com/pl/), kolejne 27,4%, a [Shopify](https://www.shopify.com/pl) tylko 5,9%. - Na telefonach 53% polskich sklepów internetowych z danymi terenowymi zalicza wszystkie trzy Core Web Vitals; na komputerach 59%. - Na telefonach najczęściej zaliczają je sklepy na Shopify (63%) i PrestaShop (60%), najrzadziej na Shoperze (33%), którego hamuje INP, czyli czas reakcji strony na dotknięcie. - Spośród dużych platform sklepy na WooCommerce mają najwolniejsze serwery i najmniej sklepów ładujących się w progu LCP. - PrestaShop obsługuje co czwarty z największych polskich sklepów internetowych, [WooCommerce](https://woocommerce.com/) co szósty; polskie platformy SaaS (Shoper, IdoSell, [AtomStore](https://www.atomstore.pl/) i inne) razem ponad jedną czwartą, Shopify mniej więcej co siedemnasty. - Co ósmy sklep ma własny silnik albo front headless. ## Najpopularniejsze platformy sklepowe w Polsce PrestaShop prowadzi z dużą przewagą, za nim WooCommerce. Shoper i IdoSell, dwie największe polskie platformy abonamentowe, idą łeb w łeb z Magento i ze sklepami pisanymi od zera. Wszystko poniżej AtomStore, od SOTESHOP i shopGold po [Shopware](https://www.shopware.com/en/) i [Sylius](https://sylius.com/), ma poniżej 2% i trafia do „innych platform”. **PrestaShop obsługuje co czwarty duży polski sklep internetowy** (Udział sklepów .pl z listy Tranco według platformy · 95-procentowe przedziały) | Pozycja | Wartość | Przedział 95% | n | | --- | --- | --- | --- | | PrestaShop | 26% | 24%–28% | 2182 | | WooCommerce | 17% | 15%–18% | 2182 | | Shoper | 10% | 9,2%–12% | 2182 | | Własny silnik | 10% | 9%–12% | 2182 | | IdoSell | 10% | 8,8%–11% | 2182 | | Magento / Adobe Commerce | 9,4% | 8,2%–11% | 2182 | | Inne platformy | 7,9% | 6,8%–9,1% | 2182 | | Shopify | 5,9% | 5%–6,9% | 2182 | | Headless | 2,1% | 1,6%–2,8% | 2182 | | AtomStore | 1,7% | 1,2%–2,3% | 2182 | Source: Badanie Outofplace, 23 września 2026; lista Tranco Y8YYG. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/pl/chart-prestashop-obsluguje-co-czwarty-duzy-polski-sklep-internetowy.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/platforms.csv ## Open source wciąż rządzi Po pogrupowaniu według tego, jak działa oprogramowanie, platformy open source na własnym serwerze albo hostingu sklepu to 54% próby. To ta część rynku, w której za szybkość odpowiada sam sklep: platforma to tylko punkt wyjścia, a resztę decydują motyw, wtyczki i serwer. Na platformie SaaS większość tego należy do dostawcy. **Ponad połowa sklepów stoi na open source utrzymywanym na własnym serwerze** (Sklepy według rodzaju platformy · n = 2182) | Pozycja | Open source na własnym serwerze | Polski SaaS | Globalny SaaS i pakiety | Własny silnik lub headless | n | | --- | --- | --- | --- | --- | --- | | Wszystkie sklepy | 54% | 27% | 6,4% | 12% | 2182 | Source: Badanie Outofplace, 23 września 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/pl/chart-ponad-polowa-sklepow-stoi-na-open-source-utrzymywanym-na-wlasnym.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/platforms.csv ## Czołówka rynku stoi na czymś innym Po posortowaniu sklepów według popularności obraz się odwraca. Wśród 100 największych prowadzi Magento z 27%, za nim własne silniki (25%) i fronty headless (12%); na Magento działają sportano.pl i gymbeam.pl, na froncie w [Nuxt](https://nuxt.com/) eobuwie.pl i modivo.pl, na [Next.js](https://nextjs.org/) zooplus.pl. PrestaShop, lider w całej próbie, obsługuje z nich tylko 6%. Od 501. sklepu w dół jest odwrotnie: PrestaShop 26,5%, WooCommerce 18,9%, a długi ogon należy do polskich platform SaaS. **Duże sklepy piszą własne albo stoją na Magento; długi ogon to PrestaShop i polski SaaS** (Udział sklepów na każdej platformie w każdym przedziale wielkości, sklepy uszeregowane według popularności · n = 100, 400 i 1682) | Pozycja | Top 100 sklepów | 101–500 | 501 i dalej | | --- | --- | --- | --- | | PrestaShop | 6% | 27% | 27% | | WooCommerce | 6% | 11% | 19% | | Shoper | 3% | 5,8% | 12% | | Własny silnik | 25% | 14% | 8,4% | | IdoSell | 8% | 6,5% | 11% | | Magento / Adobe Commerce | 27% | 19% | 6% | | Shopify | 5% | 3,8% | 6,4% | | Headless | 12% | 2,5% | 1,4% | | AtomStore | 3% | 2,8% | 1,3% | | Inne platformy | 5% | 7,8% | 8,1% | Source: Badanie Outofplace, 23 września 2026; lista Tranco Y8YYG. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/pl/chart-duze-sklepy-pisza-wlasne-albo-stoja-na-magento-dlugi-ogon-to-pre.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/shops.csv **Własne silniki i fronty headless to domena top 100** (Sklepy według rodzaju platformy w każdym przedziale wielkości) | Pozycja | Open source na własnym serwerze | Polski SaaS | Globalny SaaS i pakiety | Własny silnik lub headless | n | | --- | --- | --- | --- | --- | --- | | Top 100 sklepów | 41% | 15% | 7% | 37% | 100 | | 101–500 | 60% | 19% | 4,5% | 16% | 400 | | 501 i dalej | 53% | 30% | 6,8% | 9,9% | 1682 | Source: Badanie Outofplace, 23 września 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/pl/chart-wlasne-silniki-i-fronty-headless-to-domena-top-100.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/shops.csv ## Która platforma sklepowa jest najszybsza? Sklep zalicza Core Web Vitals, gdy trzy na cztery odsłony (75. percentyl, p75) wypadają dobrze we wszystkich trzech wskaźnikach: [Largest Contentful Paint](https://web.dev/articles/lcp?hl=pl) (LCP, ładowanie) mieści się w 2,5 sekundy, [Interaction to Next Paint](https://web.dev/articles/inp?hl=pl) (INP, szybkość reakcji) w 200 milisekundach, a [Cumulative Layout Shift](https://web.dev/articles/cls?hl=pl) (CLS, stabilność układu) nie przekracza 0,1. Google [zdecydowanie zaleca dobre wyniki Core Web Vitals](https://developers.google.com/search/docs/appearance/core-web-vitals?hl=pl), żeby „osiągnąć sukces w wyszukiwarce Google”. Na telefonach prowadzi Shopify z 63%, za nim PrestaShop z 60%; ich przedziały nakładają się na siebie i na przedziały IdoSell (57%) oraz sklepów na własnym silniku (57%). WooCommerce (48%) i Magento (46%) są poniżej średniej, która wynosi 53%. Na dole są fronty headless, AtomStore i Shoper, ten ostatni z 33%. Dwie platformy SaaS na przeciwnych końcach pokazują, ile zależy od dostawcy: na platformie abonamentowej to dostawca utrzymuje serwery i pisze dużą część kodu sklepu. **Sklepy na Shopify i PrestaShop najczęściej zaliczają Core Web Vitals na telefonach** (Odsetek sklepów, których LCP, INP i CLS na p75 są dobre na telefonach, według platformy · CrUX, 28 dni do 21 września 2026 · 95-procentowe przedziały · platformy z co najmniej 30 sklepami z danymi) | Pozycja | Wartość | Przedział 95% | n | | --- | --- | --- | --- | | Shopify | 63% | 54%–71% | 120 | | PrestaShop | 60% | 55%–64% | 462 | | IdoSell | 57% | 51%–64% | 218 | | Własny silnik | 57% | 50%–64% | 199 | | WooCommerce | 48% | 42%–54% | 284 | | Magento / Adobe Commerce | 46% | 39%–53% | 190 | | Headless | 40% | 26%–54% | 43 | | AtomStore | 39% | 25%–55% | 36 | | Shoper | 33% | 27%–39% | 223 | Source: Chrome UX Report (Google); badanie Outofplace, 23 września 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/pl/chart-sklepy-na-shopify-i-prestashop-najczesciej-zaliczaja-core-web-vi.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/crux.csv Małe polskie platformy, których nie ma na wykresie, bo każda ma mniej niż 30 sklepów z danymi, wypadają przeważnie dobrze: na telefonach zalicza 23 z 25 sklepów na SOTESHOP i 19 z 27 na shopGold. To za mało, żeby je szeregować. Na komputerach zalicza 59% sklepów, a kolejność się zmienia. INP przechodzi tam prawie wszędzie (98% sklepów), więc platformy, które traciły na szybkości reakcji, nadrabiają: fronty headless rosną z 40% na telefonach do 70% na komputerach. IdoSell idzie w drugą stronę, z 57% do 47%, bo układ jego sklepów przesuwa się na szerokich ekranach. **Na komputerach fronty headless nadrabiają, a IdoSell spada** (Odsetek sklepów zaliczających wszystkie trzy Core Web Vitals, telefony i komputery · CrUX, 28 dni do 21 września 2026) | Pozycja | Telefony | Komputery | | --- | --- | --- | | Wszystkie sklepy | 53% | 59% | | Shopify | 63% | 75% | | PrestaShop | 60% | 64% | | IdoSell | 57% | 47% | | Własny silnik | 57% | 74% | | WooCommerce | 48% | 49% | | Magento / Adobe Commerce | 46% | 49% | | Headless | 40% | 70% | | AtomStore | 39% | 53% | | Shoper | 33% | 49% | Source: Chrome UX Report (Google); badanie Outofplace, 23 września 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/pl/chart-na-komputerach-fronty-headless-nadrabiaja-a-idosell-spada.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/crux.csv ## Jak szybka jest każda platforma dla prawdziwych użytkowników Typowy polski sklep zalicza każdy wskaźnik z osobna. Mediany p75 na telefonach to 1,9 s dla LCP, 155 ms dla INP i 0,01 dla CLS. Kłopot w tym, że wszystkie trzy naraz zalicza ledwie ponad połowa sklepów. Na każdej platformie mediana LCP mieści się w 2,5 sekundy, od 1,6 s na Shopify do 2,2 s na AtomStore. Ważniejszy jest rozrzut wewnątrz platformy: środkowa połowa samych sklepów na WooCommerce rozciąga się od 1,7 s do 2,8 s, szerzej niż odstęp między najszybszą a najwolniejszą platformą. **Na każdej platformie mediana LCP na telefonach mieści się w 2,5 sekundy** (LCP każdego sklepu na p75 na telefonach, w sekundach · kropka: mediana sklepów, linia: środkowa połowa sklepów · CrUX, 28 dni do 21 września 2026) | Pozycja | Wartość | Zakres | n | | --- | --- | --- | --- | | Shopify | 1,6 s | 1,3 s–2 s | 122 | | Własny silnik | 1,8 s | 1,3 s–2,3 s | 201 | | Shoper | 1,8 s | 1,4 s–2,2 s | 223 | | Headless | 1,9 s | 1,6 s–2,3 s | 44 | | Wszystkie sklepy | 1,9 s | 1,5 s–2,4 s | 1974 | | PrestaShop | 2 s | 1,6 s–2,4 s | 476 | | IdoSell | 2 s | 1,7 s–2,3 s | 218 | | Magento / Adobe Commerce | 2,1 s | 1,7 s–2,6 s | 194 | | WooCommerce | 2,2 s | 1,7 s–2,8 s | 300 | | AtomStore | 2,2 s | 2 s–2,6 s | 36 | Source: Chrome UX Report (Google); badanie Outofplace, 23 września 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/pl/chart-na-kazdej-platformie-mediana-lcp-na-telefonach-miesci-sie-w-2-5.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/crux.csv Platformy rozchodzą się na szybkości reakcji. Shoper to jedyna platforma, na której mediana INP na telefonach przekracza próg 200 ms: 228 ms; następne są fronty headless z 185 ms. Strony na Shoperze ładują się szybko: LCP zalicza 86% sklepów na Shoperze, więcej tylko na Shopify. Opóźnienie pojawia się po dotknięciu: INP rośnie, gdy procesor telefonu jest zajęty skryptami strony. We frontach headless to nic dziwnego, bo cały sklep jest tam aplikacją JavaScript działającą w przeglądarce. **Shoper to jedyna platforma, na której mediana INP na telefonach przekracza próg** (INP każdego sklepu na p75 na telefonach, w milisekundach · kropka: mediana sklepów, linia: środkowa połowa sklepów · CrUX, 28 dni do 21 września 2026) | Pozycja | Wartość | Zakres | n | | --- | --- | --- | --- | | WooCommerce | 139 ms | 108 ms–192 ms | 284 | | PrestaShop | 141 ms | 108 ms–186 ms | 462 | | IdoSell | 146 ms | 125 ms–180 ms | 218 | | Wszystkie sklepy | 155 ms | 119 ms–203 ms | 1935 | | Własny silnik | 160 ms | 124 ms–202 ms | 199 | | AtomStore | 161 ms | 133 ms–188 ms | 36 | | Shopify | 165 ms | 137 ms–209 ms | 120 | | Magento / Adobe Commerce | 167 ms | 127 ms–203 ms | 190 | | Headless | 185 ms | 160 ms–250 ms | 43 | | Shoper | 228 ms | 173 ms–278 ms | 223 | Source: Chrome UX Report (Google); badanie Outofplace, 23 września 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/pl/chart-shoper-to-jedyna-platforma-na-ktorej-mediana-inp-na-telefonach-p.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/crux.csv ## Gdzie sklepy tracą: ładowanie, reakcja czy układ strony We wszystkich sklepach na telefonach najczęściej zawodzi INP: zalicza go 73%, wobec 79% dla LCP i 84% dla CLS. Każda platforma ma własną słabość. INP zalicza tylko 40% sklepów na Shoperze. Sklepy na WooCommerce i AtomStore tracą na ładowaniu: w progu LCP mieści się tylko 64% sklepów na WooCommerce i 64% na AtomStore. Magento jest poniżej średniej we wszystkich trzech. **Shoper i fronty headless tracą na szybkości reakcji, WooCommerce na ładowaniu** (Odsetek sklepów, których p75 jest dobre dla każdego wskaźnika na telefonach i dla wszystkich trzech naraz · CrUX, 28 dni do 21 września 2026) | Pozycja | LCP | INP | CLS | Wszystkie trzy | | --- | --- | --- | --- | --- | | Wszystkie sklepy | 79% | 73% | 84% | 53% | | Shopify | 93% | 70% | 94% | 63% | | PrestaShop | 80% | 81% | 86% | 60% | | IdoSell | 84% | 83% | 77% | 57% | | Własny silnik | 81% | 75% | 88% | 57% | | WooCommerce | 64% | 79% | 89% | 48% | | Magento / Adobe Commerce | 73% | 72% | 75% | 46% | | Headless | 80% | 53% | 84% | 40% | | AtomStore | 64% | 78% | 67% | 39% | | Shoper | 86% | 40% | 78% | 33% | Source: Chrome UX Report (Google); badanie Outofplace, 23 września 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/pl/chart-shoper-i-fronty-headless-traca-na-szybkosci-reakcji-woocommerce.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/crux.csv Na komputerach słabym punktem jest układ strony. CLS nie przekracza tam 0,1 tylko w 69% sklepów, a najgorzej wypadają IdoSell (50%), Shoper (55%) i Magento (59%). CrUX nie mówi, który element się przesuwa; najczęstsze przyczyny to obrazy bez wymiarów i treść wstawiana nad tym, co już jest na ekranie, jak wyjaśnia [poradnik Google o CLS](https://web.dev/articles/optimize-cls?hl=pl). ### Czas do pierwszego bajtu: tu widać hosting Czas do pierwszego bajtu (TTFB) nie należy do Core Web Vitals, ale czeka na niego każde ładowanie strony i widać po nim, jak sklep jest hostowany. Na Shopify mediana TTFB na telefonach to 0,4 s, a 98% sklepów na Shopify mieści się w 0,8 s, orientacyjnym celu z [poradnika Google o TTFB](https://web.dev/articles/ttfb?hl=pl). Sklepy na WooCommerce potrzebują 1,3 s, a mieści się w tym celu tylko 16%. IdoSell jest tu niemal równie wolny (1,3 s, w celu 3,2%), a mimo to LCP zalicza 84% jego sklepów, więcej niż średnio: wolny pierwszy bajt szkodzi, ale sam nie przesądza o wyniku. **Sklepy na Shopify dostają pierwszy bajt najszybciej, na WooCommerce najwolniej** (TTFB każdego sklepu na p75 na telefonach, w sekundach · kropka: mediana sklepów, linia: środkowa połowa sklepów · CrUX, 28 dni do 21 września 2026) | Pozycja | Wartość | Zakres | n | | --- | --- | --- | --- | | Shopify | 0,4 s | 0,4 s–0,5 s | 121 | | Headless | 0,8 s | 0,7 s–1,1 s | 44 | | Własny silnik | 0,9 s | 0,6 s–1,2 s | 200 | | Shoper | 0,9 s | 0,7 s–1,1 s | 223 | | Wszystkie sklepy | 1 s | 0,7 s–1,4 s | 1960 | | PrestaShop | 1,1 s | 0,8 s–1,4 s | 471 | | Magento / Adobe Commerce | 1,1 s | 0,8 s–1,6 s | 194 | | IdoSell | 1,3 s | 1,1 s–1,5 s | 218 | | AtomStore | 1,3 s | 1,1 s–1,6 s | 36 | | WooCommerce | 1,3 s | 1 s–2 s | 294 | Source: Chrome UX Report (Google); badanie Outofplace, 23 września 2026. Chart: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/charts/pl/chart-sklepy-na-shopify-dostaja-pierwszy-bajt-najszybciej-na-woocommer.png Data: https://www.outofplace.space/data/blog/core-web-vitals-polish-ecommerce/2026-09-23/crux.csv ## Jak sprawdzić Core Web Vitals swojego sklepu Platforma wyznacza punkt wyjścia; resztę decydują motyw, aplikacje albo wtyczki, obrazy i hosting. Żeby sprawdzić, gdzie jest twój sklep: **1. Sprawdź dane terenowe.** Wpisz adres sklepu w [PageSpeed Insights](https://pagespeed.web.dev/). Jeśli sklep ma dość ruchu z Chrome, na górze raportu zobaczysz te same dane CrUX, których używa to badanie, dla strony i dla całej witryny. [Raport Podstawowe wskaźniki internetowe w Search Console](https://support.google.com/webmasters/answer/9205520?hl=pl) grupuje strony według wyniku. **2. Najpierw telefony, na p75.** Wskaźnik jest zaliczony, gdy trzy na cztery wizyty mieszczą się w progu. Więcej sklepów odpada na telefonach niż na komputerach, więc zacznij od nich. **3. Popraw wskaźnik, który nie przechodzi.** Wolne LCP zaczyna się zwykle na serwerze albo na głównym zdjęciu produktu czy banerze ([optymalizacja LCP](https://web.dev/articles/optimize-lcp?hl=pl)). Słabe INP biorą się ze skryptów, które zajmują telefon, gdy klient dotyka ekranu: widżetów, menedżerów tagów, ciężkiego kodu motywu ([optymalizacja INP](https://web.dev/articles/optimize-inp?hl=pl)). CLS psują obrazy bez wymiarów i banery, które spychają stronę w dół. **4. Porównaj się z platformą.** Jeśli twój sklep wyraźnie odstaje od mediany swojej platformy w tabeli powyżej, problemem nie jest platforma, tylko motyw, dodatki albo hosting. **5. Sprawdź ponownie po czterech tygodniach.** CrUX obejmuje kroczące 28 dni, więc poprawkę widać w pełni dopiero po czterech tygodniach. ## Jak sprawdziliśmy, na jakim silniku działa sklep **1. Weź każdą domenę .pl.** Lista Tranco Y8YYG (22 września 2026) zawiera 9208 domen .pl; 8067 odpowiedziało stroną główną w HTML. **2. Rozpoznaj stronę główną.** Znaczniki w HTML, nagłówkach odpowiedzi i nazwach ciasteczek, bez uruchamiania JavaScriptu strony. Znaczniki każdej platformy pochodzą z wizytówkowych sklepów dostawców, które nie trafiły do próby. **3. Zdecyduj, co jest sklepem.** Platforma, która służy tylko do sprzedaży, czyni stronę sklepem. WooCommerce potrzebuje koszyka; strona bez znaczników platformy potrzebuje dwóch niezależnych sygnałów sklepu, w tym koszyka. Zostało 2182 sklepów. **4. Sprawdź próbę ręcznie.** Do 20 sklepów na platformę, 50 własnych silników i 30 stron niebędących sklepami porównaliśmy z dowodami. Po ważeniu udziałem platform poprawnych było 97,1% etykiet. Duże marki na Salesforce Commerce Cloud czy SAP Commerce często odpowiadają botom wyzwaniem; liczymy je jako wyzwania, nie jako sklepy nieznanej platformy. WooCommerce to najsłabsza sygnatura (85% poprawnych w kontroli), bo wtyczkę często instaluje się na stronach, które nic nie sprzedają. Z 30 stron głównych uznanych za niebędące sklepami 3 okazały się jednak sklepami. ## Jak mierzyliśmy Spis platform pochodzi z jednego przejścia 23 września 2026 przez `OutofplaceResearchBot` (zobacz, [co pobiera nasz bot i jak go zablokować](https://www.outofplace.space/pl/bot)), który najpierw czyta robots.txt i pobiera tylko stronę główną. Dane o szybkości pochodzą od Google. 24 września 2026 zapytaliśmy [API Chrome UX Report](https://developer.chrome.com/docs/crux/api?hl=pl) o każdy sklep, osobno dla telefonów i komputerów, a gdy adres nie miał rekordu, sprawdzaliśmy jego bliźniaka z www albo bez. CrUX zbiera odsłony użytkowników Chrome na Androidzie i komputerach, którzy udostępniają statystyki użytkowania (Chrome na iOS się nie liczy), ze wszystkich stron witryny, z 28 dni: tutaj od 25 sierpnia do 21 września 2026. Witryny poniżej progu ruchu, którego Google nie ujawnia, nie mają rekordu; dane dla telefonów miało 1975 z 2182 sklepów (91%), dla komputerów 1916. Sklep zalicza wskaźnik, gdy jego p75 mieści się w progu „dobry” według Google, a Core Web Vitals, gdy zalicza LCP, INP i CLS; nieliczne sklepy bez danych INP nie dają się ocenić i nie wchodzą do tego odsetka. Dla każdej platformy podajemy odsetek zaliczających z 95-procentowym przedziałem Wilsona oraz medianę p75 sklepów ze środkową połową sklepów wokół niej. Platformy z mniej niż 30 sklepami z danymi nie trafiają na wykresy, ale są w plikach, które zawierają też tygodniową historię każdego sklepu z ostatniego pół roku z API historii CrUX. Odsetek zaliczeń platformy opisuje sklepy, które ją wybrały, a nie samo oprogramowanie. Duzi sprzedawcy z własnymi programistami stawiają na Magento, własne silniki i fronty headless; małe sklepy wybierają SaaS albo tani hosting; motywy, aplikacje, obrazy i skrypty zewnętrzne różnią się między sklepami. CrUX widzi tylko Chrome na Androidzie i komputerach, uśrednia wszystkie strony witryny, także karty produktów i koszyk, i pomija sklepy ze zbyt małym ruchem. Platformę rozpoznaliśmy ze strony głównej 23 września, więc sklep, który w ciągu tych 28 dni zmienił platformę, liczymy pod nową. ## Dalsza lektura - [Web Vitals](https://web.dev/articles/vitals?hl=pl): Co mierzą LCP, INP i CLS i jakie progi stosuje Google. - [Metodologia Chrome UX Report](https://developer.chrome.com/docs/crux/methodology?hl=pl): Których użytkowników, stron i witryn dotyczą dane terenowe i jak są agregowane. - [API Chrome UX Report](https://developer.chrome.com/docs/crux/api?hl=pl): API, na którym opiera się część o szybkości: jeden rekord na witrynę i urządzenie. - [Optymalizacja Interaction to Next Paint](https://web.dev/articles/optimize-inp?hl=pl): Poradnik Google o wskaźniku, który polskie sklepy najczęściej oblewają na telefonach. - [Boty AI kontra polski internet: robots.txt 1000 stron .pl](https://www.outofplace.space/pl/blog/boty-ai-polski-internet): Nasze badanie tej samej listy: jak top 1000 stron .pl traktuje boty AI. --- # Skrypty zewnętrzne na polskich stronach: kto co ładuje (PL) Source: https://www.outofplace.space/pl/blog/skrypty-zewnetrzne-na-polskich-stronach · Published 2026-09-24 Category: Wydajność · Tags: Skrypty zewnętrzne, Google Tag Manager, Core Web Vitals, Polska > 7 na 10 polskich stron ładuje skrypty z Google, co szósta Universal Analytics, a serwisy z większą liczbą zewnętrznych firm wolniej reagują na telefonach. Siedem na dziesięć polskich stron głównych ładuje skrypty z Google, a cztery na pięć skrypty od co najmniej jednej zewnętrznej firmy. Przeczytaliśmy strony główne 7785 serwisów .pl z [listy popularnych stron Tranco](https://tranco-list.eu/list/Y8YYG/full), które odpowiedziały HTML-em, tej samej listy co w [naszym badaniu Core Web Vitals sklepów według platformy](https://www.outofplace.space/pl/blog/core-web-vitals-sklepow-internetowych), i ustaliliśmy, jakie firmy stoją za większością ładowanych przez nie skryptów. Mediana to kod od 2 zewnętrznych firm na stronę, a 16% stron wciąż ładuje Universal Analytics, którego standardowa wersja [przestała przetwarzać dane](https://support.google.com/analytics/answer/11583528?hl=pl) w lipcu 2023 roku. Potem sprawdziliśmy te strony w [Chrome UX Report](https://developer.chrome.com/docs/crux?hl=pl), czyli danych Google o tym, jak szybko strony działają dla prawdziwych użytkowników Chrome. Serwisy, których strony główne ładują więcej zewnętrznych firm, wolniej reagują na telefonach: [Interaction to Next Paint](https://web.dev/articles/inp?hl=pl) (INP, czas reakcji strony na dotknięcie) zalicza 79% serwisów z jedną albo dwiema, ale tylko 48% z dziesięcioma lub więcej. W sklepach internetowych spadek jest wyraźniejszy, a na pozostałych stronach odsetek trzyma się aż do dziewięciu. - 82% stron głównych .pl ładuje kod co najmniej jednej zewnętrznej firmy; mediana to 2, a 14% stron ładuje sześć lub więcej. - Skrypty z Google ładuje 70% wszystkich stron głównych, 40% przez Google Tag Managera. Skrypty z Mety ładuje 20%. - 16% stron głównych wciąż ładuje Universal Analytics, którego standardowa wersja nie działa od lipca 2023 roku; 616 z nich nie ma obok Google Analytics 4, Google tag ani Tag Managera. - INP na telefonach zalicza 79% stron głównych z jedną albo dwiema zewnętrznymi firmami i tylko 48% z dziesięcioma lub więcej. W sklepach spadek jest wyraźniejszy niż na pozostałych stronach. ## Co to są skrypty zewnętrzne? Skrypt zewnętrzny (third-party script) to JavaScript, który strona ładuje od innej firmy niż jej właściciel. Część robi coś, co odwiedzający widzi: okno czatu, mapę, widżet płatności, baner cookies; większość raportuje o odwiedzającym komuś innemu: analityka, piksele reklamowe, mapy ciepła. Każdy kosztuje przeglądarkę połączenie i trochę pracy w głównym wątku, tym samym, który odpowiada na dotknięcia. [Przewodnik Google po zewnętrznym JavaScripcie](https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript?hl=pl) ostrzega, że obciążające procesor parsowanie i wykonywanie skryptów może opóźniać reakcję na działania użytkownika. Zewnętrzną firmę liczymy raz na stronę główną, niezależnie od liczby plików: czy to tag script wskazuje na jej serwery, czy fragment instalacyjny inline ładuje jej kod, jak robią typowe fragmenty Google Tag Managera albo piksela Mety. Skrypt z innej domeny liczymy jako zewnętrzny także wtedy, gdy ta domena należy do grupy właściciela strony. ## Jakie skrypty zewnętrzne ładują polskie strony Tagi Google prowadzą z dużą przewagą: sam Google Tag Manager jest na 40% stron głównych. Najczęstszy tag spoza Google to piksel Mety (Meta Pixel), na 15%. Wysoko jest też skrypt Cloudflare Web Analytics, który Cloudflare [dodaje domyślnie](https://developers.cloudflare.com/web-analytics/get-started/) do stron obsługiwanych przez swoje proxy, gdy właściciel włączy Web Analytics (stan na 24 września 2026). **Google Tag Manager jest na czterech na dziesięć polskich stron głównych** (Odsetek stron głównych .pl ładujących kod danego dostawcy, 20 najczęstszych · n = 7785 · 95-procentowe przedziały) | Pozycja | Wartość | Przedział 95% | n | | --- | --- | --- | --- | | Google Tag Manager | 40% | 39%–41% | 7785 | | Google Analytics 4 | 26% | 25%–27% | 7785 | | Universal Analytics (UA-) | 16% | 15%–16% | 7785 | | Meta Pixel | 15% | 15%–16% | 7785 | | Google Ads | 11% | 10%–12% | 7785 | | Google reCAPTCHA | 9,8% | 9,1%–10% | 7785 | | Cloudflare Web Analytics | 9,4% | 8,7%–10% | 7785 | | Google AdSense | 7% | 6,5%–7,6% | 7785 | | jsDelivr | 6,6% | 6,1%–7,2% | 7785 | | Facebook SDK | 6,4% | 5,9%–7% | 7785 | | cdnjs | 5,1% | 4,6%–5,6% | 7785 | | Google Hosted Libraries | 4,3% | 3,8%–4,7% | 7785 | | jQuery CDN | 3,7% | 3,3%–4,1% | 7785 | | Microsoft Clarity | 3,6% | 3,2%–4% | 7785 | | Cookiebot | 3,5% | 3,1%–3,9% | 7785 | | Google Ad Manager | 3,5% | 3,1%–3,9% | 7785 | | TrustMate | 2,9% | 2,5%–3,3% | 7785 | | Hotjar | 2,6% | 2,3%–3% | 7785 | | edrone | 2,5% | 2,2%–2,9% | 7785 | | Shoper | 2,5% | 2,2%–2,9% | 7785 | Source: Spis Outofplace, 24 września 2026; lista Tranco Y8YYG. Chart: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/charts/pl/chart-google-tag-manager-jest-na-czterech-na-dziesiec-polskich-stron-g.png Data: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/2026-09-24/vendors.csv To wartości minimalne. Menedżer tagów ładuje kolejne tagi dopiero po wczytaniu strony i tych nie ma w HTML: strona główna z Google Tag Managerem może przez niego uruchamiać Google Analytics, piksel Mety i mapę ciepła, a tu liczy się jako jedna zewnętrzna firma. ### Co szósta strona główna wciąż ładuje Universal Analytics Google zastąpiło Universal Analytics usługą Google Analytics 4, a standardowe usługi Universal Analytics przestały przetwarzać dane 1 lipca 2023 roku. Tag, który do nich raportuje (identyfikator `UA-`, przez gtag.js, analytics.js albo jeszcze starszy ga.js), wciąż jednak pobiera się i uruchamia przy każdej wizycie, choć Google nie przetwarza już jego danych. Na 616 stronach (7,9% wszystkich stron głównych) martwy tag to jedyna analityka Google w HTML: obok nie ma Google Analytics 4, Google tag ani Tag Managera. [Google Optimize](https://support.google.com/optimize/answer/12979939?hl=pl), narzędzie Google do testów A/B wyłączone 30 września 2023 roku, wciąż jest na 14 stronach głównych. ## Do czego służą skrypty: analityka, menedżery tagów, reklamy Po pogrupowaniu według zadania prowadzi zewnętrzna analityka (51% stron głównych), a za nią menedżery tagów (40%). Piksele reklamowe i automatyzacja marketingu, czyli tagi raportujące reklamodawcom wizyty i sprzedaż, są na 26%. **Połowa polskich stron głównych ładuje zewnętrzną analitykę** (Odsetek stron głównych .pl z co najmniej jedną zewnętrzną firmą danego rodzaju · n = 7785 · 95-procentowe przedziały) | Pozycja | Wartość | Przedział 95% | n | | --- | --- | --- | --- | | Analityka, monitoring | 51% | 50%–52% | 7785 | | Menedżery tagów | 40% | 39%–42% | 7785 | | Piksele, marketing | 26% | 25%–27% | 7785 | | Biblioteki z CDN | 17% | 17%–18% | 7785 | | Osadzenia i widżety | 12% | 12%–13% | 7785 | | Reklamy na stronie | 12% | 12%–13% | 7785 | | Captcha i logowanie | 12% | 11%–12% | 7785 | | Banery zgody | 10% | 9,7%–11% | 7785 | | Opinie i odznaki | 7,1% | 6,6%–7,7% | 7785 | | Płatności i dostawa | 5,5% | 5%–6% | 7785 | | Platforma i hosting | 5,3% | 4,8%–5,8% | 7785 | | Czat, obsługa klienta | 4,7% | 4,2%–5,2% | 7785 | | Szukanie, rekomendacje | 2,6% | 2,2%–2,9% | 7785 | | Push i pop-upy | 2,5% | 2,2%–2,9% | 7785 | | Testy A/B | 0,7% | 0,6%–1% | 7785 | Source: Spis Outofplace, 24 września 2026. Chart: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/charts/pl/chart-polowa-polskich-stron-glownych-laduje-zewnetrzna-analityke.png Data: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/2026-09-24/kinds.csv Tylko 10% ładuje baner zgody z serwerów platformy do zarządzania zgodami, takiej jak Cookiebot (3,5%). Nie znaczy to, że reszta o zgodę nie pyta: baner podawany z własnej domeny strony, na przykład jako wtyczka do CMS-a, nie jest skryptem zewnętrznym i tu się nie liczy. Spośród wszystkich wykryć dostawców w 3,6% wszystkie skrypty były w HTML wstrzymane, dopóki zgoda albo wtyczka opóźniająca ładowanie ich nie uruchomi. ## Ile zewnętrznych firm ładuje jedna strona Większość ładuje kilka: mediana to kod od 2 zewnętrznych firm na stronę. 18% stron głównych nie ładuje żadnego skryptu zewnętrznego, a dziesięć lub więcej ładuje tylko 1,2%. **Mediana polskiej strony głównej to kod od dwóch zewnętrznych firm** (Strony główne według liczby zewnętrznych firm, których skrypty ładują · n = 7785) | Zakres | stron głównych | | --- | --- | | 0–1 | 1423 | | 1–2 | 1462 | | 2–3 | 1314 | | 3–4 | 1123 | | 4–5 | 829 | | 5–6 | 537 | | 6–7 | 383 | | 7–8 | 339 | | 8–9 | 190 | | 9–10 | 94 | | 10–11 | 50 | | 11–12 | 14 | | 12–13 | 11 | | 13–14 | 7 | | 14–15 | 3 | | 15–16 | 5 | | 16–17 | 1 | Source: Spis Outofplace, 24 września 2026. Chart: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/charts/pl/chart-mediana-polskiej-strony-glownej-to-kod-od-dwoch-zewnetrznych-fir.png Data: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/2026-09-24/sites.csv ## Czy skrypty zewnętrzne spowalniają stronę? Każdy skrypt to praca dla telefonu. Żeby sprawdzić, czy widać to u prawdziwych użytkowników, zestawiliśmy strony główne z danymi z Chrome UX Report. Ma je 79% serwisów; reszta ma za mało ruchu z Chrome. Im więcej zewnętrznych firm, tym rzadziej strona zalicza INP, czyli reaguje na dotknięcie w 200 ms, które Google uznaje za dobry wynik. Między jedną a pięcioma firmami różnica jest niewielka. Od sześciu odsetek spada, a przy dziesięciu i więcej zalicza już tylko mniej więcej co druga strona. **Strony z sześcioma lub więcej zewnętrznymi firmami rzadziej zaliczają INP niż te z jedną do pięciu** (Odsetek serwisów z p75 INP na telefonach (cały serwis, tak jak mierzy CrUX) do 200 ms według liczby zewnętrznych firm na stronie głównej · kropka: odsetek, linia: 95-procentowy przedział · CrUX, 28 dni do 22 września 2026) | Pozycja | Wartość | Zakres | n | | --- | --- | --- | --- | | Brak | 70% | 67%–74% | 647 | | 1–2 | 79% | 77%–80% | 2042 | | 3–5 | 78% | 76%–79% | 2194 | | 6–9 | 72% | 69%–75% | 959 | | 10 i więcej | 48% | 38%–58% | 90 | Source: Chrome UX Report (Google); spis Outofplace, 24 września 2026. Chart: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/charts/pl/chart-strony-z-szescioma-lub-wiecej-zewnetrznymi-firmami-rzadziej-zali.png Data: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/2026-09-24/by_third_parties.csv Rośnie też sam czas reakcji. Typowa strona (mediana) ma INP 129 ms przy jednej albo dwóch zewnętrznych firmach i 202 ms przy dziesięciu i więcej, czyli tuż za granicą dobrego wyniku. **Od jednej albo dwóch zewnętrznych firm w górę typowa strona reaguje wolniej** (Mediana p75 INP na telefonach (cały serwis, tak jak mierzy CrUX) według liczby zewnętrznych firm na stronie głównej · kropka: mediana, linia: środkowa połowa serwisów · tło: progi Google · CrUX, 28 dni do 22 września 2026) | Pozycja | Wartość | Zakres | n | | --- | --- | --- | --- | | Brak | 143 ms | 94 ms–213 ms | 647 | | 1–2 | 129 ms | 96 ms–188 ms | 2042 | | 3–5 | 145 ms | 111 ms–193 ms | 2194 | | 6–9 | 159 ms | 128 ms–206 ms | 959 | | 10 i więcej | 202 ms | 161 ms–252 ms | 90 | Source: Chrome UX Report (Google); spis Outofplace, 24 września 2026. Chart: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/charts/pl/chart-od-jednej-albo-dwoch-zewnetrznych-firm-w-gore-typowa-strona-reag.png Data: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/2026-09-24/by_third_parties.csv Strony główne bez żadnej zewnętrznej firmy wyłamują się z tego wzoru: zalicza tylko 70% z nich. To jednak inna grupa. W CrUX jest tylko 50% z nich, wobec 76% stron z jedną albo dwiema firmami, więc to prawdopodobnie głównie mniejsze serwisy, w których wolne INP może mieć inne przyczyny. ### W sklepach spadek zaczyna się od sześciu zewnętrznych firm Sklepy i pozostałe strony zachowują się inaczej. W sklepach odsetek zaliczających INP spada od sześciu zewnętrznych firm, a przy dziesięciu i więcej zalicza go tylko 44% z nich (61 sklepów z danymi, więc przedział jest szeroki). Na pozostałych stronach linia jest prawie płaska do dziewięciu firm; stron z dziesięcioma i więcej jest tam za mało, żeby coś o nich powiedzieć. **W sklepach spadek INP zaczyna się od sześciu zewnętrznych firm** (Odsetek serwisów zaliczających INP na telefonach (cały serwis, tak jak mierzy CrUX), sklepy wobec pozostałych stron, według liczby zewnętrznych firm na stronie głównej · grupy z co najmniej 30 serwisami każdego rodzaju · CrUX, 28 dni do 22 września 2026) | Pozycja | Sklepy | Pozostałe strony | | --- | --- | --- | | Brak | 67% | 71% | | 1–2 | 79% | 78% | | 3–5 | 77% | 78% | | 6–9 | 65% | 79% | Source: Chrome UX Report (Google); spis Outofplace, 24 września 2026. Chart: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/charts/pl/chart-w-sklepach-spadek-inp-zaczyna-sie-od-szesciu-zewnetrznych-firm.png Data: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/2026-09-24/by_third_parties.csv Sklepów nie dzieliliśmy według platform. Platforma, która podaje swój kod z innej domeny, idzie w parze z niższym wynikiem (niżej), więc część spadku może wynikać z platformy, a nie z liczby firm. ### Które rodzaje skryptów idą w parze z wolniejszą stroną 6 rodzajów nie zmienia wyniku w granicach błędu: strony z menedżerem tagów, pikselami reklamowymi, banerem zgody, powiadomieniami push, płatnościami i dostawą albo osadzeniami zaliczają INP podobnie często jak strony bez nich. 6 rodzajów idzie w parze z rzadziej zaliczanym INP: testy A/B (na nielicznych stronach), zewnętrzna wyszukiwarka albo rekomendacje, kod platformy podawany z innej domeny, widżety opinii, czat i reklamy. Pozostałe 3, czyli zewnętrzna analityka, biblioteki z CDN i captcha, idą w parze z odrobinę częściej zaliczanym INP. **Testy A/B, zewnętrzna wyszukiwarka i widżety opinii idą w parze z rzadziej zaliczanym INP, menedżery tagów nie** (Odsetek serwisów zaliczających INP na telefonach (cały serwis, tak jak mierzy CrUX) wśród stron głównych z danym rodzajem zewnętrznej firmy i bez niego · CrUX, 28 dni do 22 września 2026) | Pozycja | Strony z nim | Strony bez niego | n | | --- | --- | --- | --- | | Testy A/B | 47% | 76% | 55 | | Szukanie, rekomendacje | 57% | 77% | 197 | | Platforma i hosting | 61% | 77% | 390 | | Opinie i odznaki | 67% | 77% | 538 | | Czat, obsługa klienta | 71% | 76% | 324 | | Reklamy na stronie | 72% | 77% | 874 | | Płatności i dostawa | 73% | 76% | 400 | | Push i pop-upy | 75% | 76% | 193 | | Banery zgody | 75% | 76% | 737 | | Piksele, marketing | 75% | 76% | 1821 | | Menedżery tagów | 76% | 76% | 2884 | | Osadzenia i widżety | 78% | 76% | 834 | | Biblioteki z CDN | 79% | 75% | 1096 | | Captcha i logowanie | 79% | 75% | 732 | | Analityka, monitoring | 78% | 74% | 3252 | Source: Chrome UX Report (Google); spis Outofplace, 24 września 2026. Chart: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/charts/pl/chart-testy-a-b-zewnetrzna-wyszukiwarka-i-widzety-opinii-ida-w-parze-z.png Data: https://www.outofplace.space/data/blog/third-party-scripts-polish-web/2026-09-24/kinds.csv Strona, która ładuje więcej zewnętrznych firm, różni się też wielkością, celem i wykonaniem. Żadna z tych różnic nie dowodzi, że spowodowały ją skrypty. ## Czy Google Tag Manager spowalnia stronę? Sam w sobie, na ile pokazują dane terenowe, nie. Strony główne z Google Tag Managerem zaliczają INP na telefonach w 76% przypadków, bez niego w 76%, a ta różnica mieści się w granicach błędu. Liczy się to, co kontener ładuje, a tego nie widać w HTML. Własny [przewodnik Google po tagach i menedżerach tagów](https://web.dev/articles/tag-best-practices?hl=pl) wprost mówi o korelacji między rozmiarem menedżera tagów a gorszymi wynikami INP (stan na 24 września 2026). Pytanie nie brzmi więc, czy strona używa menedżera tagów, tylko co w nim jest. ## Jak znaleźć i odchudzić skrypty zewnętrzne na swojej stronie **1. Wypisz, co się ładuje.** Otwórz stronę główną w Chrome z DevTools, przeładuj ją z panelem Network przefiltrowanym do JS i posortuj według domeny. Wszystko spoza twojej domeny to skrypty zewnętrzne. Potem otwórz menedżer tagów: jego tagi ładują się po stronie i nie ma ich w HTML. **2. Usuń to, co martwe.** Tagi Universal Analytics i Google Optimize nic już nie robią, a wciąż się pobierają i uruchamiają. Tak samo tagi zakończonych kampanii i narzędzi, do których nikt się nie loguje. Przewodnik Google po tagach zauważa, że wstrzymanie albo usunięcie tagu w Tag Managerze usuwa jego kod z kontenera, a zablokowanie nie (stan na 24 września 2026). **3. Ładuj widżety wtedy, gdy są potrzebne.** Czat, mapa czy odtwarzacz wideo mogą poczekać, aż odwiedzający o nie poprosi: pokaż przycisk albo nieruchomy obrazek i załaduj skrypt przy pierwszym kliknięciu. **4. Sprawdź dane terenowe.** Wpisz adres strony w [PageSpeed Insights](https://pagespeed.web.dev/): jeśli strona ma dość ruchu z Chrome, na górze raportu zobaczysz te same dane CrUX co w tym badaniu. Zacznij od INP, wskaźnika, który cierpi, gdy skrypty zajmują główny wątek; [przewodnik Google po optymalizacji INP](https://web.dev/articles/optimize-inp?hl=pl) pokazuje, jak znaleźć skrypty stojące za wolną reakcją. **5. Zmierz ponownie po czterech tygodniach.** CrUX obejmuje kroczące 28 dni, więc zmianę widać w pełni dopiero po czterech tygodniach. ## Jak mierzyliśmy Strony główne pochodzą z naszego spisu z 24 września 2026 roku, przeprowadzonego przez `OutofplaceResearchBot` (zobacz, [co pobiera nasz crawler i jak go zablokować](https://www.outofplace.space/pl/bot)), który najpierw czyta robots.txt i pobiera tylko stronę główną: 8023 z 9208 domen .pl z listy Tranco odpowiedziało HTML-em, a po połączeniu domen przekierowujących pod ten sam adres zostało 7785 różnych serwisów. HTML każdej strony głównej czytaliśmy bez uruchamiania. Skrypt się liczy, gdy tag script ładuje go z innej domeny albo gdy fragment instalacyjny inline ładuje kod znanego dostawcy; JSON-LD i inne bloki danych się nie liczą. Tabela 187 dostawców, zbudowana z hostów skryptów widzianych na co najmniej pięciu stronach głównych, wskazuje firmę i rodzaj zadania dla 91% znalezionych zewnętrznych firm, liczonych raz na stronę główną; domena skryptu spoza tabeli liczy się jako jedna niesklasyfikowana firma na każdej stronie głównej, która ją ładuje. Skrypt wstrzymany do czasu zgody też się liczy: uruchomi się, gdy odwiedzający się zgodzi. Dane o szybkości pochodzą od Google. 24 września 2026 roku zapytaliśmy [API Chrome UX Report](https://developer.chrome.com/docs/crux/api?hl=pl) o adres każdej strony głównej na telefonach, a gdy adres nie miał rekordu, o jego bliźniaka z www albo bez. CrUX zbiera odsłony użytkowników Chrome na Androidzie i komputerach, którzy udostępniają statystyki użytkowania, ze wszystkich podstron serwisu, przez 28 dni. Strona zalicza INP, gdy jego 75. percentyl nie przekracza 200 ms. Podział według liczby zewnętrznych firm (brak, 1–2, 3–5, 6–9, 10 i więcej) ustaliliśmy przed przeczytaniem danych terenowych; sklepy rozpoznaje klasyfikator z naszego badania sklepów internetowych. Dla 15 najczęstszych dostawców wylosowaliśmy po 8 wykryć w ustalonej losowej kolejności i przeczytaliśmy HTML za każdym z nich. 119 ze 120 było trafnych. Jedyny błąd to baner zgody, którego tag script miał w atrybucie type typograficzne cudzysłowy, więc przeglądarka nigdy go nie uruchamia. Widzieliśmy tylko stronę główną, w takim HTML-u, w jakim przyszła, i nic z niej nie uruchamialiśmy: skrypty dodawane później przez menedżer tagów albo inny skrypt są niewidoczne, więc każdy odsetek to wartość minimalna, a liczby na stronę zaniżają serwisy z rozbudowanymi menedżerami tagów. Strona główna dłuższa niż 1 MiB była w tym miejscu ucinana (331 takich). Dane terenowe obejmują wszystkie podstrony serwisu, nie tylko stronę główną, i tylko serwisy z dostatecznym ruchem z Chrome. Strony, które ładują więcej zewnętrznych firm, różnią się też wielkością, celem i wykonaniem, więc żadna z opisanych różnic nie dowodzi, że to skrypty ją spowodowały. ## Warto przeczytać - [Sprawdzone metody dotyczące tagów i menedżerów tagów](https://web.dev/articles/tag-best-practices?hl=pl): Przewodnik zespołu Chrome o tym, jak menedżer tagów może nie spowalniać strony. - [Wczytywanie JavaScriptu innej firmy](https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript?hl=pl): Jak skrypty zewnętrzne kosztują czas ładowania i szybkość reakcji i jak ładować je z mniejszą szkodą. - [Interaction to Next Paint (INP)](https://web.dev/articles/inp?hl=pl): Co mierzy INP i jakich progów używa Google. - [Google Analytics 4 zastąpiło Universal Analytics](https://support.google.com/analytics/answer/11583528?hl=pl): Komunikat Google o tym, kiedy Universal Analytics przestało przetwarzać dane. - [Core Web Vitals sklepów: która platforma jest najszybsza?](https://www.outofplace.space/pl/blog/core-web-vitals-sklepow-internetowych): Nasze badanie tej samej listy: Core Web Vitals polskich sklepów internetowych według platformy. --- # Boty AI kontra polski internet: robots.txt 1000 stron .pl (PL) Source: https://www.outofplace.space/pl/blog/boty-ai-polski-internet · Published 2026-09-23 Category: Wyszukiwanie i AI · Tags: boty AI, robots.txt, GPTBot, llms.txt, Polska > Sprawdziliśmy plik robots.txt 1000 największych stron .pl: co piąta blokuje boty AI, głównie treningowe jak GPTBot, rzadko wyszukiwarki AI. Jak to rozdzielić? 23 września 2026 nasz crawler [OutofplaceResearchBot](https://www.outofplace.space/pl/bot) przeczytał plik robots.txt tysiąca najpopularniejszych stron w domenie .pl, żebyśmy mogli sprawdzić, które boty AI wpuszczają. 20,5% z nich blokuje co najmniej jednego bota AI. Statystycznie to tyle samo, co w światowym top 1000, gdzie odsetek wynosi 22,7%. Różnica leży w tym, _których_ botów to dotyczy. Polskie strony zamykają drzwi przed botami zbierającymi dane treningowe, a wyszukiwarki AI w większości wpuszczają. Bota wyszukiwarki AI blokuje tylko 5,4% z nich, przy 13,9% na świecie. Jeśli chcesz pojawiać się w odpowiedziach ChatGPT, Claude'a czy Perplexity, to właściwa kolejność. Tyle że czasem wychodzi przypadkiem: [stara lista skopiowana raz i nigdy nieaktualizowana](#listy-sie-starzeja). - Co piąta strona z top 1000 .pl blokuje w robots.txt jakiegoś bota AI, tyle samo co w światowym top 1000. - GPTBot jest najczęściej blokowanym botem w Polsce i na świecie: 15,1% i 15,4%. - Polskie strony blokują trening, nie wyszukiwanie. Spośród stron blokujących GPTBota mniej niż jedna trzecia blokuje też OAI-SearchBota; na świecie ponad połowa. - Liczy się wielkość: boty AI blokuje jedna trzecia stron z top 100 .pl i co szósta z miejsc 501–1000. - Co siódma polska strona blokująca boty nie napisała tych reguł sama: używa [zarządzanego robots.txt od Cloudflare](#zarzadzany-robotstxt-od-cloudflare-i-content-signals). W próbie światowej nie znaleźliśmy ani jednej takiej. ## Boty AI: co to jest i jakie są rodzaje „Bot AI” to trzy różne zadania i dostawcy dają dziś każdemu osobny user agent. To rozróżnienie decyduje o wszystkim, co dalej: - **Boty treningowe** zbierają strony do trenowania modeli: [GPTBot](https://developers.openai.com/api/docs/bots) (OpenAI), [ClaudeBot](https://support.claude.com/en/articles/8896518-does-anthropic-crawl-data-from-the-web-and-how-can-site-owners-block-the-crawler) (Anthropic), [Google-Extended](https://developers.google.com/crawling/docs/crawlers-fetchers/google-common-crawlers?hl=pl), [Applebot-Extended](https://support.apple.com/pl-pl/119829), [CCBot](https://commoncrawl.org/ccbot) (Common Crawl), Bytespider (ByteDance), meta-externalagent (Meta), [Amazonbot](https://developer.amazon.com/amazonbot). - **Boty wyszukiwarek AI** indeksują strony, żeby asystent mógł je znaleźć i zacytować: OAI-SearchBot, Claude-SearchBot, [PerplexityBot](https://docs.perplexity.ai/docs/resources/perplexity-crawlers), [DuckAssistBot](https://duckduckgo.com/duckduckgo-help-pages/results/duckassistbot). - **Boty pobierające na prośbę użytkownika** otwierają stronę, bo ktoś poprosił o to asystenta: ChatGPT-User, Claude-User, Perplexity-User, meta-externalfetcher, [MistralAI-User](https://docs.mistral.ai/robots). Blokada bota treningowego trzyma strony z dala od przyszłych modeli. Blokada bota wyszukiwarki albo bota pobierającego usuwa je z odpowiedzi i z linków w tych odpowiedziach. Dwa z „botów” treningowych niczego nie pobierają. Google-Extended i Applebot-Extended to tylko tokeny: stronę ściąga [Googlebot](https://developers.google.com/search/docs/crawling-indexing/googlebot?hl=pl) albo Applebot, a token mówi Google'owi i Apple, czy wolno na niej trenować. Ich blokada zostawia stronę w wyszukiwarkach Google i Apple, a blokada Google-Extended nie wyłącza też [AI Overviews](https://developers.google.com/search/docs/appearance/ai-features?hl=pl): te słuchają reguł dla Googlebota. Drugi wyjątek to boty pobierające. OpenAI, Perplexity i Meta piszą, że ich boty mogą w ogóle nie stosować się do robots.txt, bo o stronę poprosił człowiek; Anthropic deklaruje, że Claude-User się stosuje. ## Polska blokuje tak często jak świat, ale nie te same boty Licząc wszystkie boty AI, różnica między próbą .pl a światową wynosi 2,2 punktu procentowego, dobrze w granicach błędu. Po podziale według przeznaczenia obraz się zmienia. Boty treningowe są blokowane równie często. Boty wyszukiwarek AI i boty pobierające na prośbę użytkownika – w Polsce ponad dwa razy rzadziej. **Polska blokuje trening tak często jak świat, wyszukiwarki AI dużo rzadziej** (Odsetek stron, których robots.txt blokuje stronę główną co najmniej jednemu botowi danego rodzaju · n = 1000 w każdej próbie · 23 września 2026) | Pozycja | Top 1000 .pl | Globalny top 1000 | | --- | --- | --- | | Dowolny bot AI | 21% | 23% | | Boty treningowe | 21% | 22% | | Boty wyszukiwarek AI | 5,4% | 14% | | Pobieranie na prośbę użytkownika | 5,3% | 13% | Source: Badanie Outofplace; lista Tranco Y8YYG. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/pl/chart-polska-blokuje-trening-tak-czesto-jak-swiat-wyszukiwarki-ai-duzo.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/domains.csv ### GPTBot czy OAI-SearchBot: dwa osobne przełączniki Najwyraźniej widać to u poszczególnych dostawców. Spośród polskich stron blokujących GPTBota OAI-SearchBota blokuje też 28%. W próbie światowej – 56%. U Anthropic różnica jest jeszcze większa: 24% wobec 60%. **Większość polskich stron blokujących trening zostawia wyszukiwarki AI otwarte** (Strony blokujące bota treningowego danego dostawcy (GPTBot, ClaudeBot) według tego, czy blokują też jego bota wyszukiwarki (OAI-SearchBot, Claude-SearchBot)) | Pozycja | Blokuje też wyszukiwanie | Blokuje tylko trening | n | | --- | --- | --- | --- | | OpenAI · Polska | 28% | 72% | 151 | | OpenAI · Świat | 56% | 44% | 154 | | Anthropic · Polska | 24% | 76% | 107 | | Anthropic · Świat | 60% | 40% | 152 | Source: Badanie Outofplace, 23 września 2026. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/pl/chart-wiekszosc-polskich-stron-blokujacych-trening-zostawia-wyszukiwar.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/bot_policies.csv Na świecie strona, która blokuje boty AI, zwykle blokuje też te wyszukujące. W Polsce typowa strona wymienia kilka botów treningowych i na tym kończy: 11,2% polskiej próby blokuje wyłącznie trening, prawie dwa razy więcej niż 5,9% na świecie. ## Które boty AI są blokowane najczęściej Prowadzi GPTBot: 15,1% polskich stron i 15,4% na świecie. OpenAI ogłosiło go w sierpniu 2023 i od niego zaczyna się większość list blokad. Dalej są CCBot z Common Crawl, Amazonbot, Bytespider od ByteDance i ClaudeBot. Najnowsze boty są ledwo widoczne: Claude-SearchBota blokuje 2,7% polskich stron, głównie dlatego, że listy powstały, zanim się pojawił. **GPTBot to najczęściej blokowany bot AI na stronach .pl** (Odsetek domen z top 1000 .pl, których robots.txt blokuje danemu botowi stronę główną · 95-procentowe przedziały · wyróżnione boty treningowe) | Pozycja | Wartość | Przedział 95% | n | | --- | --- | --- | --- | | GPTBot | 15% | 13%–17% | 1000 | | CCBot | 13% | 11%–16% | 1000 | | Amazonbot | 12% | 10%–14% | 1000 | | Bytespider | 12% | 9,7%–14% | 1000 | | ClaudeBot | 11% | 8,9%–13% | 1000 | | meta-externalagent | 11% | 8,8%–13% | 1000 | | Google-Extended | 8,4% | 6,8%–10% | 1000 | | Applebot-Extended | 8,4% | 6,8%–10% | 1000 | | ChatGPT-User | 4,7% | 3,6%–6,2% | 1000 | | PerplexityBot | 4,6% | 3,5%–6,1% | 1000 | | OAI-SearchBot | 4,4% | 3,3%–5,9% | 1000 | | meta-externalfetcher | 4% | 3%–5,4% | 1000 | | DuckAssistBot | 3,7% | 2,7%–5,1% | 1000 | | Perplexity-User | 3,5% | 2,5%–4,8% | 1000 | | Claude-SearchBot | 2,7% | 1,9%–3,9% | 1000 | | Claude-User | 2,3% | 1,5%–3,4% | 1000 | | MistralAI-User | 2,3% | 1,5%–3,4% | 1000 | Source: Badanie Outofplace, 23 września 2026. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/pl/chart-gptbot-to-najczesciej-blokowany-bot-ai-na-stronach-pl.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/summary_by_bot.csv Prawie wszystko to świadome decyzje. Strona, która w grupie `User-agent: *` zabrania wszystkiego, blokuje każdego bota bez własnej grupy, AI czy nie. Ta „podłoga” odpowiada w przypadku GPTBota tylko za 1,9% polskich stron; reszta wymienia bota z nazwy. Poniżej polski i światowy odsetek dla każdego bota obok siebie. Obie próby zgadzają się co do botów treningowych. Rozchodzą się przy wszystkim, co służy odpowiedziom. **Różnica pojawia się przy wyszukiwarkach i botach pobierających** (Odsetek stron blokujących danemu botowi stronę główną · top 1000 .pl wobec światowego top 1000) | Pozycja | Top 1000 .pl | Globalny top 1000 | | --- | --- | --- | | GPTBot | 15% | 15% | | CCBot | 13% | 18% | | Amazonbot | 12% | 13% | | Bytespider | 12% | 17% | | ClaudeBot | 11% | 15% | | meta-externalagent | 11% | 14% | | Google-Extended | 8,4% | 14% | | Applebot-Extended | 8,4% | 13% | | ChatGPT-User | 4,7% | 11% | | PerplexityBot | 4,6% | 13% | | OAI-SearchBot | 4,4% | 8,9% | | meta-externalfetcher | 4% | 9,9% | | DuckAssistBot | 3,7% | 9,5% | | Perplexity-User | 3,5% | 10% | | Claude-SearchBot | 2,7% | 9,2% | | Claude-User | 2,3% | 9,5% | | MistralAI-User | 2,3% | 9,6% | Source: Badanie Outofplace, 23 września 2026. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/pl/chart-roznica-pojawia-sie-przy-wyszukiwarkach-i-botach-pobierajacych.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/summary_by_bot.csv ## Większe strony blokują częściej Im popularniejsza strona, tym częściej blokuje. Co najmniej jednego bota AI blokuje 33% ze stu najpopularniejszych domen .pl i 15,8% z miejsc od 501 do 1000. Spadek jest bardziej stromy niż w próbie światowej, gdzie wynosi od 27% do 21,2%. Największe polskie strony to wydawcy, marketplace'y i portale: firmy, które mają najwięcej tekstu do ochrony i prawników, którzy zadają to pytanie. **Jedna trzecia stron z top 100 .pl blokuje boty AI** (Odsetek blokujących co najmniej jednego bota AI według miejsca w próbie · n = 100, 400 i 500) | Pozycja | Top 1000 .pl | Globalny top 1000 | | --- | --- | --- | | Top 100 | 33% | 27% | | 101–500 | 23% | 24% | | 501–1000 | 16% | 21% | Source: Badanie Outofplace, 23 września 2026. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/pl/chart-jedna-trzecia-stron-z-top-100-pl-blokuje-boty-ai.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/domains.csv Efekt wielkości widać przy każdym bocie z osobna. GPTBota blokuje 23% stron z top 100 i 11,6% stron z miejsc od 501 do 1000; każdy bot treningowy idzie tym samym spadkiem. Boty wyszukiwarek zostają nisko przy każdej wielkości. **Największe strony .pl najczęściej blokują boty treningowe, a wyszukiwarki rzadko niezależnie od wielkości** (Odsetek stron .pl blokujących danemu botowi stronę główną według miejsca w próbie · n = 100, 400 i 500) | Pozycja | Top 100 | 101–500 | 501–1000 | | --- | --- | --- | --- | | GPTBot | 23% | 18% | 12% | | CCBot | 21% | 16% | 9,6% | | Amazonbot | 16% | 16% | 8,8% | | Bytespider | 19% | 14% | 8% | | ClaudeBot | 14% | 13% | 8,6% | | meta-externalagent | 15% | 14% | 6,8% | | Google-Extended | 12% | 11% | 5,8% | | Applebot-Extended | 11% | 11% | 5,6% | | OAI-SearchBot | 7% | 4,3% | 4% | | PerplexityBot | 6% | 4,8% | 4,2% | | Claude-SearchBot | 4% | 2,3% | 2,8% | Source: Badanie Outofplace, 23 września 2026. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/pl/chart-najwieksze-strony-pl-najczesciej-blokuja-boty-treningowe-a-wyszu.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/bot_policies.csv Instytucje publiczne blokują rzadziej i nie celowo. Bota AI blokuje 11,9% spośród 42 domen gov.pl w próbie i 16,1% spośród 31 domen edu.pl; obie grupy są małe, więc traktuj to jako kierunek. Większość tych blokad to w ogóle nie polityka wobec AI. sejm.gov.pl, dziennikustaw.gov.pl i wroclaw.sa.gov.pl [wpuszczają Googlebota i zabraniają wszystkim innym](https://www.sejm.gov.pl/robots.txt), co odcina każdego bota AI, a razem z nimi Binga i DuckDuckGo. W przypadku Sejmu i Dziennika Ustaw oznacza to też, że Copilot i wyszukiwarka ChatGPT nie przeczytają źródeł, o które ludzie ich pytają. ## Listy się starzeją Listy blokad pisze się raz i kopiuje latami. 7,2% polskich stron wciąż blokuje `anthropic-ai`, nazwę, której Anthropic przestał używać (dokumentacja wymienia dziś ClaudeBota, Claude-SearchBota i Claude-User), a Claude-SearchBota tylko 2,7%. W 4,1% próby lista jest nieaktualna w sposób, który ma znaczenie: blokuje starą nazwę, a bota, który ją zastąpił, przepuszcza. Trzeba oddać Anthropic, że [powiedział 404 Media w 2024 roku](https://www.404media.co/websites-are-blocking-the-wrong-ai-scrapers-because-ai-companies-keep-making-new-ones/), iż ClaudeBot respektuje reguły zapisane dla dwóch wycofanych nazw. To dobra wola, nie standard: według [RFC 9309](https://www.rfc-editor.org/rfc/rfc9309.html) reguła dla `anthropic-ai` ClaudeBota nie dotyczy, a następny dostawca, który zmieni nazwę bota, może nie być tak hojny. Porządne boty go czytają i się stosują; nic ich do tego nie zmusza. Nazwane grupy nie dziedziczą też niczego z `User-agent: *`: bot stosuje się do jednej grupy, która go wymienia, i ignoruje resztę. Jeśli dajesz botom wyszukiwarek AI własną grupę `Allow`, powtórz w niej swoje prywatne ścieżki. ## Zarządzany robots.txt od Cloudflare i Content Signals 3,1% polskich stron serwuje [zarządzany robots.txt od Cloudflare](https://developers.cloudflare.com/bots/additional-configurations/managed-robots-txt/): jeden przełącznik w panelu i CDN dokleja przed plikiem strony blok reguł, który sam aktualizuje. Blok zabrania dostępu dokładnie ośmiu botom treningowym z naszej listy, od GPTBota po Amazonbota, i żadnemu botowi wyszukiwarki. Te strony, w tym regionalne tytuły Polska Press, takie jak poranny.pl, nto.pl, pomorska.pl i gazetawroclawska.pl, to 15,1% wszystkich polskich stron blokujących boty AI i 24% stron blokujących tylko trening. Częściowo tłumaczą, czemu Polska skłania się w tę stronę, ale nie w całości: bez nich blokowanie samego treningu i tak jest częstsze niż w próbie światowej, gdzie zarządzanego pliku nie znaleźliśmy wcale. Duże międzynarodowe serwisy piszą własne. Ten przełącznik widać w liczbach. Za Cloudflare boty AI blokuje 25,6% polskich stron, a poza nim 18,2%. Na świecie jest odwrotnie. **W Polsce strony za Cloudflare blokują częściej** (Odsetek blokujących co najmniej jednego bota AI według tego, czy strona idzie przez Cloudflare) | Pozycja | Za Cloudflare | Inny hosting | | --- | --- | --- | | Polska | 26% | 18% | | Świat | 19% | 24% | Source: Badanie Outofplace, 23 września 2026. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/pl/chart-w-polsce-strony-za-cloudflare-blokuja-czesciej.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/domains.csv Zarządzany plik zawiera też linię `Content-Signal` (`search=yes, ai-train=no`), część [Content Signals Policy](https://contentsignals.org/), którą Cloudflare opublikował we wrześniu 2025, by deklarować, do czego wolno używać treści: wyszukiwanie, dane wejściowe dla AI, trening AI. W ten sposób `ai-train=no` deklaruje 3,9% polskich stron i 1,6% na świecie. Jeśli tester robots.txt oznacza `Content-Signal` jako nieznaną dyrektywę, to normalne i nieszkodliwe: według RFC 9309 bot pomija linie, których nie rozumie. 79% tych linii pochodzi z zarządzanego pliku, a nie od kogoś, kto je wpisał. ## Co to jest llms.txt i kto go ma? [`llms.txt`](https://llmstxt.org) to plik Markdown, który mówi modelom językowym, czym jest serwis i gdzie są najważniejsze strony; [zaproponował go Jeremy Howard](https://www.answer.ai/posts/2024-09-03-llmstxt.html) we wrześniu 2024. Specyfikacja wymaga tylko nagłówka H1 z nazwą serwisu; my wymagaliśmy też co najmniej jednego linku, bo plik bez linków nigdzie nie prowadzi. Taki plik pod `/llms.txt` serwuje 9,2% polskiej próby. Kolejne 10% odpowiada pod `/llms.txt` stroną HTML ze statusem 200 i to właśnie dostaje model, który próbuje go przeczytać, a niedbały checker liczy jako „ma llms.txt”. Pierwsze były firmy hostingowe: home.pl, nazwa.pl, cyberfolks.pl, dhosting.pl i kei.pl serwują poprawny plik, podobnie mbank.pl, t-mobile.pl, rossmann.pl, mediamarkt.pl, a z instytucji publicznych uokik.gov.pl. Google pisze, że [jego wyszukiwarka ten plik ignoruje](https://developers.google.com/search/docs/fundamentals/ai-optimization-guide?hl=pl); jest dla innych asystentów. Sami też go udostępniamy: [nasz llms.txt](https://www.outofplace.space/llms.txt) wymienia nasze badania, case studies i usługi, a [llms-full.txt](https://www.outofplace.space/llms-full.txt) zawiera pełny tekst każdego wpisu. **Większość stron nie ma llms.txt; co dziesiąta odpowiada stroną WWW** (Co zwróciło GET /llms.txt · n = 1000 w każdej próbie · błędy i ścieżki, których nie wolno nam było pobrać, liczymy jako brak) | Pozycja | Poprawny llms.txt | Zły format | Strona HTML (soft 404) | Brak | n | | --- | --- | --- | --- | --- | --- | | Top 1000 .pl | 9,2% | 2,4% | 10% | 78% | 1000 | | Globalny top 1000 | 14% | 3,4% | 9,6% | 74% | 1000 | Source: Badanie Outofplace, 23 września 2026. Chart: https://www.outofplace.space/data/blog/ai-crawlers-polish-web/charts/pl/chart-wiekszosc-stron-nie-ma-llms-txt-co-dziesiata-odpowiada-strona-ww.png Data: https://www.outofplace.space/data/blog/ai-bots-polish-web/2026-09-23/domains.csv ## Reszta sieci czytelnej dla maszyn Boty czytają więcej niż robots.txt. Polskie strony są tu blisko świata w podstawach i odstają w szczegółach, które pomagają maszynie umiejscowić stronę: [alternatywach `hreflang`](https://developers.google.com/search/docs/specialty/international/localized-versions?hl=pl) i [mapie strony wskazanej tam, gdzie boty jej szukają](https://www.sitemaps.org/protocol.html#submit_robots). [Kompresja Zstandard](https://www.rfc-editor.org/rfc/rfc8878.html) jest na stronach głównych .pl kilka razy częstsza, ale to znowu Cloudflare: wszystkie polskie strony, które ją wysłały, poza jedną, szły przez ten CDN. ## Trzy polityki warte skopiowania Niektóre polskie strony wyraźnie to przemyślały. Każdy z tych plików sprawdziliśmy ręcznie w dniu badania. - **Trening nie, odpowiedzi tak.** Tytuły Wirtualnej Polski (wp.pl, o2.pl, money.pl, pudelek.pl, abczdrowie.pl, dobreprogramy.pl) [zabraniają dostępu GPTBotowi, CCBotowi i Bytespiderowi](https://www.wp.pl/robots.txt), a OAI-SearchBotowi, ChatGPT-User, PerplexityBotowi i Perplexity-User dają własne grupy `Allow: /`. Wydawca, który mówi dokładnie, czego chce. - **Wszyscy mile widziani, z imienia.** mediamarkt.pl i euro.com.pl mają [grupy `Allow: /`](https://mediamarkt.pl/robots.txt) dla GPTBota, ClaudeBota, OAI-SearchBota, Claude-SearchBota, PerplexityBota i innych. Dla sprzedawcy asystent polecający produkt to witryna sklepowa. - **Niech listę prowadzi CDN.** Regionalne tytuły Polska Press używają zarządzanego pliku Cloudflare, który blokuje boty treningowe i pozostaje aktualny bez niczyjej edycji. ## Jak zablokować ChatGPT i inne boty AI w robots.txt ### Czy blokować boty AI? Nie ma jednej dobrej polityki. Wydawca, który sprzedaje archiwum, ma inne interesy niż sklep, który chce być polecany. Ale cokolwiek wybierzesz, wybieraj według przeznaczenia bota, nie według dostawcy: ### robots.txt, który blokuje trening i zostawia wyszukiwarki AI Tak wygląda robots.txt, który blokuje trening i zostawia wyszukiwarki AI. Grupa treningowa to te same osiem botów, które blokuje zarządzany plik Cloudflare. Nasza strona robi odwrotnie i [wpuszcza wszystkie boty](https://www.outofplace.space/robots.txt), bo blog studia jest po to, żeby go cytowano. ```txt title="robots.txt" # Wyszukiwarki AI i pobieranie na prośbę użytkownika: cytują i linkują User-agent: OAI-SearchBot User-agent: ChatGPT-User User-agent: Claude-SearchBot User-agent: Claude-User User-agent: PerplexityBot User-agent: Perplexity-User Allow: / # Nazwane grupy nie dziedziczą z *, więc powtórz prywatne ścieżki Disallow: /koszyk/ Disallow: /konto/ # Trenowanie modeli User-agent: GPTBot User-agent: ClaudeBot User-agent: Google-Extended User-agent: Applebot-Extended User-agent: CCBot User-agent: Bytespider User-agent: meta-externalagent User-agent: Amazonbot Disallow: / # Wszyscy pozostali, w tym Googlebot i Bingbot User-agent: * Disallow: /koszyk/ Disallow: /konto/ Sitemap: https://www.example.pl/sitemap.xml ``` **1. Zdecyduj według przeznaczenia.** Trening, wyszukiwarki AI, pobieranie na prośbę użytkownika. Zapisz, czego chcesz dla każdego, zanim dotkniesz pliku. **2. Wpisz aktualne nazwy.** Bierz je [ze stron dostawców](#dalsza-lektura), nie z listy, którą ktoś wrzucił w 2023. **3. Powtórz prywatne ścieżki w każdej nazwanej grupie.** Bot, który pasuje do nazwanej grupy, całkowicie ignoruje `User-agent: *`. **4. Przetestuj.** Wklej plik do narzędzia poniżej i sprawdź ścieżki, które są dla ciebie ważne. **5. Pokryj to, czego robots.txt nie obejmie.** Copilot jeździ na Bingbocie, więc steruje się nim [meta tagami `noarchive` i `nocache`](https://www.bing.com/webmasters/help/robots-meta-tags-and-attributes-that-bing-supports-5198d240). AI Overviews w Google słuchają Googlebota i [ustawień fragmentów, np. `nosnippet`](https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag?hl=pl). Boty pobierające, które mogą ignorować robots.txt, zatrzyma dopiero reguła w CDN albo na serwerze. **6. Sprawdzaj co kwartał.** Nowe boty pojawiają się kilka razy w roku. Nieaktualna lista jest gorsza niż żadna, bo wygląda jak decyzja. Wklej tu swój robots.txt, żeby zobaczyć, co może pobrać każdy bot AI. Działa w przeglądarce, na tym samym parserze, którego użyliśmy w badaniu; nic nie jest nigdzie wysyłane. ## Jak mierzyliśmy Wzięliśmy [listę Tranco Y8YYG](https://tranco-list.eu/list/Y8YYG/full) (utworzona 22 września 2026, okno 30 dni, pięć źródeł) i szliśmy od góry, zbierając pierwsze 1000 domen .pl, których serwer odpowiedział. Próba kontrolna to pierwsze 1000 domen z tej samej listy, przetworzone tak samo. 23 września nasz bot pobrał robots.txt i stronę główną każdej domeny, a także `/llms.txt`, `/llms-full.txt` i mapę strony. Przedstawiał się jako `OutofplaceResearchBot` z linkiem do strony opisującej badanie. Każdy robots.txt parsowaliśmy zgodnie z RFC 9309 i sprawdzaliśmy ścieżkę strony głównej `/` dla 38 user agentów: 36 botów AI od 17 operatorów, łącznie z wycofanymi nazwami, oraz Googlebota i Bingbota dla porównania. Wykresy pokazują nazwy, które operatorzy obecnie dokumentują. Bot jest zablokowany, jeśli reguła, która go dotyczy, zabrania `/`, niezależnie od tego, czy jest wymieniony z nazwy, czy spada do `*`. Odsetki mają 95-procentowe przedziały Wilsona, różnice między próbami – przedziały Newcombe'a. Próba to pierwsze 1000 domen .pl z listy Tranco, które odpowiedziały na nasze zapytania. 23 z nich zabrania naszemu botowi dostępu do strony głównej w robots.txt; ich robots.txt i tak przeczytaliśmy (z definicji jest publiczny), ale nic więcej nie pobieraliśmy. Domeny z błędem DNS, odrzuconym połączeniem albo błędem serwera pomijaliśmy i braliśmy następną z listy. Przy 1000 stron 95-procentowy przedział dla głównego wyniku wynosi od 18,1% do 23,1%. Każda strona dostaje jedną klasę, wygrywa pierwsze dopasowanie. Blokada całkowita: zablokowany jest też Googlebot, więc reguła nie dotyczy AI. Wszystkie boty AI: zablokowane są wszystkie boty treningowe i co najmniej jeden bot wyszukiwarki lub pobierający. Nieaktualna lista: zablokowana jest nazwa, której dostawca już nie dokumentuje, a bot, który ją zastąpił, nie. Tylko trening: zablokowane boty treningowe, żaden bot wyszukiwarki ani pobierający. Niespójna: zablokowany bot wyszukiwarki lub pobierający, a przepuszczony bot treningowy. Otwarta: żaden bot AI nie jest zablokowany. Reguły i ich testy są w repozytorium. robots.txt to tylko to, o co strona prosi. Część stron blokuje boty AI na firewallu lub w CDN, a część każdemu botowi pokazuje wyzwanie; wyzwania liczyliśmy osobno i nigdy jako „wpuszczone”. Sprawdzaliśmy tylko ścieżkę strony głównej: strona, która blokuje botom artykuły, ale nie `/`, liczy się jako otwarta. Domena .pl to nie to samo co polska firma, a listy popularności faworyzują duże serwisy. Liczby opisują najczęściej odwiedzaną część polskiego internetu w jednym dniu. ## Dalsza lektura - [RFC 9309: Robots Exclusion Protocol](https://www.rfc-editor.org/rfc/rfc9309.html): Standard robots.txt: grupy, dopasowanie i co bot musi zrobić, gdy pliku nie ma albo jest niedostępny. - [OpenAI: Overview of OpenAI crawlers](https://developers.openai.com/api/docs/bots): GPTBot, OAI-SearchBot i ChatGPT-User oraz do czego służy każdy z nich. - [Anthropic: jak zablokować boty](https://support.claude.com/en/articles/8896518-does-anthropic-crawl-data-from-the-web-and-how-can-site-owners-block-the-crawler): ClaudeBot, Claude-SearchBot i Claude-User. - [Google: Common crawlers, w tym Google-Extended](https://developers.google.com/crawling/docs/crawlers-fetchers/google-common-crawlers?hl=pl): Co kontroluje Google-Extended, a czego nie. - [Cloudflare: Managed robots.txt](https://developers.cloudflare.com/bots/additional-configurations/managed-robots-txt/): Co blokuje plik włączany jednym kliknięciem i jaką linię Content-Signal dodaje. - [llms.txt: propozycja i jej format](https://llmstxt.org): Oryginalna specyfikacja: gdzie leży plik i jak jest zbudowany. - [OutofplaceResearchBot: co pobiera i jak go zablokować](https://www.outofplace.space/pl/bot): Kto uruchamia nasz bot, jak się przedstawia i jak uprzejmie pobiera strony. --- # Next.js prefetch zmierzony: Partial Prefetching w 16.3 (PL) Source: https://www.outofplace.space/pl/blog/nextjs-prefetch-zmierzony · Published 2026-09-23 Category: Wydajność · Tags: Next.js, Prefetching, React > Partial Prefetching w Next.js 16.3 zmniejszył w naszym benchmarku prefetch nawet o 93%, ale treść adresu przychodzi po kliknięciu. Kiedy co się opłaca. [Next.js 16.3](https://nextjs.org/blog/next-16-3) zmienia to, czym jest Next.js prefetch. Z włączonym [`partialPrefetching`](https://nextjs.org/docs/app/api-reference/config/next-config-js/partialPrefetching) App Router nie pobiera już payloadu dla każdego linku na ekranie: pobiera jeden wspólny szkielet na trasę, a treść zależną od adresu zostawia na po kliknięciu. Zbudowaliśmy jedną aplikację na sześć sposobów i przeklikaliśmy ją 3744 razy, żeby sprawdzić, co ta zamiana daje i ile kosztuje. Na stronie dokumentacji ze 100 linkami w bocznym menu prefetch zmalał o 93%. Ceną jest czas: treść, która wcześniej była na ekranie niemal od razu, przychodzi teraz kilkaset milisekund po kliknięciu, za szkieletem strony. Która strona tej zamiany jest lepsza, zależy od strony i od [jednego szczegółu Reacta, który łatwo przeoczyć](#szkielet-ktory-zobaczysz-300-ms). - Partial Prefetching zmniejszył prefetch o 78–93% na stronach z wieloma linkami, a całą nawigację w dokumentacji mniej więcej jedenastokrotnie. - Szkielet pojawia się od razu. Treść zależna od adresu przychodzi po kliknięciu: 345 ms w dokumentacji wobec 52 ms przy samym Cache Components, na zwolnionym telefonie. - Szkielet, który się pojawi, zostaje na około 300 ms, bo React tyle wstrzymuje każde odsłonięcie. - Linki z `prefetch={true}` zostają natychmiastowe w każdej konfiguracji. - `prefetchInlining` zostaw domyślny; HTTP/2 nie zmienił niczego ważnego. ## Co zmienia Partial Prefetching Do wersji 16.3 [App Router](https://nextjs.org/docs/app) robił prefetch dla każdego linku: gdy na ekran wjeżdżało N linków, pobierał mniej więcej N payloadów. Z `partialPrefetching` (wymaga [`cacheComponents`](https://nextjs.org/docs/app/api-reference/config/next-config-js/cacheComponents)) pobiera jeden [App Shell](https://nextjs.org/docs/app/guides/adopting-partial-prefetching) na trasę: wszystko, co strona renderuje niezależnie od adresu. Linki do tej samej trasy dzielą ten jeden prefetch. Treść, która czyta `params` albo `searchParams`, rozwiązuje się po kliknięciu, chyba że link poprosi o więcej przez `prefetch={true}`. Porównaliśmy sześć buildów tej samej aplikacji: - **L0**, bez Cache Components: klasyczny App Router. - **C0**, samo Cache Components. - **P0**, Cache Components z Partial Prefetching i domyślnym inliningiem prefetchu. - **P1–P3**, to samo z wyłączonym inliningiem, z małymi progami i z dużymi. Każdy przeklikaliśmy w trzech nawigacjach: z katalogu 48 produktów na stronę produktu, ze strony dokumentacji ze 100 linkami w menu na inną stronę dokumentacji i z wyników wyszukiwania na inne wyszukiwanie przez jeden z ośmiu linków z `prefetch={true}`. ## Bajty prefetchu: nawet o 93% mniej W dokumentacji samo Cache Components pobierało z wyprzedzeniem każdy widoczny link z menu. Partial Prefetching zmienił to z 402 kB → 29 kB (−93%), w 8,5 żądaniach zamiast 49. W katalogu oszczędność wyniosła 78%. Wyszukiwanie prawie się nie zmieniło, bo jego osiem linków z `prefetch={true}` nadal pobiera własne wyniki. **Partial Prefetching pobiera ułamek bajtów na stronach z wieloma linkami** (Skompresowane bajty RSC pobrane przed kliknięciem · komputer, bez ograniczeń, późne kliknięcie · mediany z 20 przebiegów) | Pozycja | Katalog → produkt | Dokumentacja → dokumentacja | Wyszukiwanie → wyszukiwanie | | --- | --- | --- | --- | | L0 · Klasyczny router | 30 kB | 408 kB | 98 kB | | C0 · Cache Components | 160 kB | 402 kB | 163 kB | | P0 · Partial Prefetching | 34 kB | 29 kB | 107 kB | | P1 · Bez inliningu | 33 kB | 32 kB | 105 kB | | P2 · Mały inlining | 32 kB | 28 kB | 103 kB | | P3 · Duży inlining | 34 kB | 33 kB | 105 kB | Source: Benchmark Outofplace, Next.js 16.3.6. Chart: https://www.outofplace.space/data/blog/nextjs-prefetch-benchmark/charts/pl/chart-partial-prefetching-pobiera-ulamek-bajtow-na-stronach-z-wieloma.png Data: https://www.outofplace.space/data/blog/nextjs-partial-prefetching-benchmark/2026-09-23/summary_by_variant.csv Jeden wiersz zasługuje na drugie spojrzenie. Włączenie Cache Components bez Partial Prefetching sprawiło, że katalog pobierał pięć razy więcej niż klasyczny router, 30 kB → 160 kB (+426%): prerenderowane szkielety produktów da się wtedy pobrać osobno dla każdego linku. Jeśli włączasz Cache Components na stronach z wieloma linkami, od razu zdecyduj o Partial Prefetching. ## Czy nawigacja jest naprawdę natychmiastowa? Szkielet tak. Przy Partial Prefetching pojawiał się 43 ms–45 ms po kliknięciu na zwolnionym telefonie. Z tym, po co ktoś kliknął, czyli produktem albo artykułem, jest inaczej: potrzebuje żądania po kliknięciu. **Samo Cache Components pokazuje treść od razu, Partial Prefetching po jednym żądaniu** (Od kliknięcia do pierwszej klatki z treścią zależną od adresu · telefon, ograniczenie Lighthouse mobile, późne kliknięcie · ms) | Pozycja | L0 · Klasyczny router | C0 · Cache Components | P0 · Partial Prefetching | | --- | --- | --- | --- | | Katalog → produkt | 375 ms | 60 ms | 262 ms | | Dokumentacja → dokumentacja | 47 ms | 52 ms | 345 ms | | Wyszukiwanie → wyszukiwanie | 40 ms | 41 ms | 43 ms | Source: Benchmark Outofplace, Next.js 16.3.6. Chart: https://www.outofplace.space/data/blog/nextjs-prefetch-benchmark/charts/pl/chart-samo-cache-components-pokazuje-tresc-od-razu-partial-prefetching.png Data: https://www.outofplace.space/data/blog/nextjs-partial-prefetching-benchmark/2026-09-23/summary_by_variant.csv W dokumentacji samo Cache Components pokazało nowy artykuł po 52 ms, Partial Prefetching po 345 ms. Na stronie produktu różnica była mniejsza, 60 ms → 262 ms (+337%), a najwolniejszy był klasyczny router, bo dla dynamicznej trasy nie miał nic wyrenderowanego z góry. Wyszukiwanie, gdzie każdy link ma `prefetch={true}`, pokazywało treść po 40 ms–43 ms w każdej konfiguracji. ### Szkielet, który zobaczysz: 300 ms Na stronie produktu trzy etapy przychodzą po kolei: szkielet, produkt, a potem część renderowana w chwili żądania. **Przy Partial Prefetching strona przychodzi w trzech krokach** (Katalog → produkt · telefon, zwolniony, późne kliknięcie · od kliknięcia do każdego etapu na ekranie · ms) | Pozycja | Szkielet | Treść | Część z serwera | | --- | --- | --- | --- | | L0 · Klasyczny router | 375 ms | 375 ms | 375 ms | | C0 · Cache Components | 60 ms | 60 ms | 342 ms | | P0 · Partial Prefetching | 47 ms | 262 ms | 562 ms | Source: Benchmark Outofplace, Next.js 16.3.6. Chart: https://www.outofplace.space/data/blog/nextjs-prefetch-benchmark/charts/pl/chart-przy-partial-prefetching-strona-przychodzi-w-trzech-krokach.png Data: https://www.outofplace.space/data/blog/nextjs-partial-prefetching-benchmark/2026-09-23/summary_by_variant.csv W dokumentacji szkielet był widoczny przez 298 ms w każdym buildzie z Partial Prefetching. To nie jest czas sieci: odpowiedź dochodziła po 250 ms. React dołączony do Next.js 16.3.6 (`19.3.0-canary`) [czeka 300 ms](https://github.com/react/react/blob/d083ec1da1e5252abd3ddfdde6dfbc09701a2c51/packages/react-reconciler/src/ReactFiberWorkLoop.js#L528) od ostatniej zamiany między fallbackiem [Suspense](https://react.dev/reference/react/Suspense) a treścią, zanim zatwierdzi kolejną, żeby stan ładowania nie mignął. Efekt uboczny: etapy się łańcuchują. Szkielet, który się pojawi, zostaje na ekranie około 300 ms, nawet gdy dane już są, a osobna granica dla danych z serwera odsłania się 300 ms po poprzedniej. Projektuj szkielety tak, żeby dało się na nie patrzeć, i rozważ jedną granicę tam, gdzie dwie tylko by się łańcuchowały. ### Wczesne kliknięcie Kliknięcie 50 ms po hydratacji, zanim skończy się jakikolwiek prefetch, zabiera przewagę wszystkim, którzy pobierają z wyprzedzeniem. Samo Cache Components jest wtedy mniej więcej tak samo wolne jak Partial Prefetching, bo obie konfiguracje najpierw pokazują fallback, a potem odczekują 300 ms. **Przy wczesnym kliknięciu żadna konfiguracja niczego jeszcze nie pobrała** (Kliknięcie 50 ms po hydratacji · telefon, zwolniony · od kliknięcia do treści · ms) | Pozycja | L0 · Klasyczny router | C0 · Cache Components | P0 · Partial Prefetching | | --- | --- | --- | --- | | Katalog → produkt | 367 ms | 374 ms | 389 ms | | Dokumentacja → dokumentacja | 262 ms | 528 ms | 529 ms | | Wyszukiwanie → wyszukiwanie | 234 ms | 404 ms | 339 ms | Source: Benchmark Outofplace, Next.js 16.3.6. Chart: https://www.outofplace.space/data/blog/nextjs-prefetch-benchmark/charts/pl/chart-przy-wczesnym-kliknieciu-zadna-konfiguracja-niczego-jeszcze-nie.png Data: https://www.outofplace.space/data/blog/nextjs-partial-prefetching-benchmark/2026-09-23/summary_by_variant.csv Ostatni etap, czyli część z serwera, dzieli te kliknięcia na dwie grupy. Przy Partial Prefetching w 6 z 12 wczesnych kliknięć na stronie produktu cała strona była na ekranie po 375 ms–400 ms. W pozostałych 6 dopiero po 650 ms–700 ms, a pomiędzy nie trafił żaden przebieg. Ta przerwa to mniej więcej 300 ms, które React odczekuje między dwoma odsłonięciami: ostatni etap pojawia się razem z produktem albo jedno odczekanie później. **Ostatni etap przychodzi razem z produktem albo mniej więcej 300 ms później** (Katalog → produkt, wczesne kliknięcie · Partial Prefetching · telefon, zwolniony, przebieg HTTP/2 · od kliknięcia do ostatniego etapu na ekranie · ms) | Zakres | przebiegi | | --- | --- | | 375 ms–400 ms | 6 | | 400 ms–425 ms | 0 | | 425 ms–450 ms | 0 | | 450 ms–475 ms | 0 | | 475 ms–500 ms | 0 | | 500 ms–525 ms | 0 | | 525 ms–550 ms | 0 | | 550 ms–575 ms | 0 | | 575 ms–600 ms | 0 | | 600 ms–625 ms | 0 | | 625 ms–650 ms | 0 | | 650 ms–675 ms | 3 | | 675 ms–700 ms | 3 | Source: Benchmark Outofplace, Next.js 16.3.6. Chart: https://www.outofplace.space/data/blog/nextjs-prefetch-benchmark/charts/pl/chart-ostatni-etap-przychodzi-razem-z-produktem-albo-mniej-wiecej-300.png Data: https://www.outofplace.space/data/blog/nextjs-partial-prefetching-benchmark/2026-09-23/runs.csv ## Cały rachunek Partial Prefetching przenosi bajty sprzed kliknięcia na po kliknięciu, a na stronie produktu dodatkowo je podwaja: odpowiedź nawigacji niosła dwie pełne kopie payloadu produktu, 13 kB → 26 kB (+99%) po kompresji. Licząc wszystko, co pobiera nawigacja, razem z prefetchem, w dokumentacji i tak wychodzi daleko do przodu. **Cała nawigacja w dokumentacji kosztuje mniej więcej jedną dziesiątą bajtów** (Wszystkie skompresowane bajty RSC jednej nawigacji w dokumentacji, prefetch i nawigacja · telefon, zwolniony, późne kliknięcie) | Pozycja | Wartość | n | | --- | --- | --- | | L0 · Klasyczny router | 463 kB | 20 | | C0 · Cache Components | 458 kB | 20 | | P0 · Partial Prefetching | 40 kB | 20 | | P1 · Bez inliningu | 43 kB | 20 | | P2 · Mały inlining | 39 kB | 20 | | P3 · Duży inlining | 44 kB | 20 | Source: Benchmark Outofplace, Next.js 16.3.6. Chart: https://www.outofplace.space/data/blog/nextjs-prefetch-benchmark/charts/pl/chart-cala-nawigacja-w-dokumentacji-kosztuje-mniej-wiecej-jedna-dziesi.png Data: https://www.outofplace.space/data/blog/nextjs-partial-prefetching-benchmark/2026-09-23/summary_by_variant.csv Mniej więcej 11 razy mniej bajtów w dokumentacji i 2,2 raza mniej w katalogu. Hydratacja i opóźnienie reakcji na stronie startowej nie zmieniły się w żadnej konfiguracji. ## Kiedy `prefetch={true}` się opłaca [``](https://nextjs.org/docs/app/api-reference/components/link#prefetch) pobiera też dane z adresu strony docelowej, więc kliknięcie jest tak samo natychmiastowe jak przy pełnym prefetchu. Płacisz za każdy widoczny link: osiem linków wyszukiwania kosztowało 107 kB, więcej niż cała strona dokumentacji przy Partial Prefetching. Używaj go tam, gdzie kliknięcie jest prawdopodobne, a dane da się cache'ować: podpowiedzi wyszukiwania, link „dalej”, kilka pierwszych wyników. Na siatkach kart rób prefetch na zamiar (najechanie albo dotknięcie), zamiast oznaczać każdą kartę. ## prefetchInlining: zostaw włączony [`experimental.prefetchInlining`](https://nextjs.org/docs/app/api-reference/config/next-config-js/prefetchInlining) łączy małe odpowiedzi prefetchu w jedną. Ustawienie domyślne i nasze dwa zestawy progów różniły się najwyżej jednym żądaniem i kilkoma kilobajtami, bez mierzalnej różnicy w czasie. Wyłączenie inliningu dodało pięć albo sześć żądań w katalogu i wyszukiwaniu, a przez HTTP/1.1 kosztowało to wczesne kliknięcie w katalogu: sześć połączeń na host się zapycha. Przez [HTTP/2](https://www.rfc-editor.org/rfc/rfc9113.html) kara znikała. Wszystkie inne konfiguracje wypadły na obu protokołach tak samo. **HTTP/2 ma znaczenie tylko przy wyłączonym inliningu** (Katalog → produkt, wczesne kliknięcie · telefon, zwolniony · od kliknięcia do treści · HTTP/1.1 i HTTP/2 na przemian, po 12 przebiegów · ms) | Pozycja | HTTP/1.1 | HTTP/2 | | --- | --- | --- | | L0 · Klasyczny router | 365 ms | 363 ms | | C0 · Cache Components | 375 ms | 373 ms | | P0 · Partial Prefetching | 387 ms | 386 ms | | P1 · Bez inliningu | 440 ms | 372 ms | | P2 · Mały inlining | 390 ms | 383 ms | | P3 · Duży inlining | 387 ms | 386 ms | Source: Benchmark Outofplace, Next.js 16.3.6. Chart: https://www.outofplace.space/data/blog/nextjs-prefetch-benchmark/charts/pl/chart-http-2-ma-znaczenie-tylko-przy-wylaczonym-inliningu.png Data: https://www.outofplace.space/data/blog/nextjs-partial-prefetching-benchmark/2026-09-23/summary_by_variant.csv ## Którą konfigurację wybrać ```ts title="next.config.ts" const nextConfig: NextConfig = { cacheComponents: true, // Jeden App Shell na trasę zamiast prefetchu na każdy link. partialPrefetching: true, }; ``` ```tsx title="Linki, przy których czekanie by bolało" {suggestion} ``` **1. Policz linki.** Najwięcej zyskują strony z wieloma linkami do tej samej dynamicznej trasy: dokumentacja, siatki, feedy. Strona z kilkoma linkami do różnych stron zyskuje niewiele. **2. Zdecyduj dla każdej trasy.** Tam, gdzie natychmiastowa treść jest ważniejsza niż bajty, a strony są statyczne, zostaw pełny prefetch; gdzie indziej włącz Partial Prefetching. [Konfiguracja segmentu `export const prefetch = 'partial'`](https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config/prefetch) pozwala przechodzić trasa po trasie. **3. Oznacz prawdopodobne kliknięcia.** Dodaj `prefetch={true}` tam, gdzie następne kliknięcie da się przewidzieć, a dane da się cache'ować. **4. Zaprojektuj szkielet.** Na wolnym łączu będzie widoczny przez około 300 ms. Tytuł i nawigację umieść w części niezależnej od adresu: pojawia się niemal od razu. Ta strona działa na Partial Prefetching: większość naszych stron ma mało linków, a te, które mają ich dużo (blog, case studies), są statyczne i lekkie. Nasze własne produkty, Portivo, Sprawna Matura i Levera, też stoją na Next.js. ## Jak mierzyliśmy Wygenerowaną aplikację App Router (katalog 48 produktów, 100 stron dokumentacji z menu w layoucie, strona wyszukiwania) zbudowaliśmy sześć razy na Next.js 16.3.6, zmieniając tylko `cacheComponents`, `partialPrefetching` i `experimental.prefetchInlining`, i serwowaliśmy przez `next start`. Headless Chrome otwierał stronę startową w świeżym kontekście przeglądarki, czekał i klikał link, zapisując każde żądanie przez [protokół DevTools](https://chromedevtools.github.io/devtools-protocol/) i mierząc znaczniki od zdarzenia kliknięcia do następnej klatki animacji. Każda kombinacja konfiguracji, scenariusza, telefonu albo komputera, szybkiej albo [zwolnionej sieci (150 ms, 1,6 Mb/s, CPU 4×)](https://github.com/GoogleChrome/lighthouse/blob/main/docs/throttling.md) i wczesnego albo późnego kliknięcia przeszła 20 razy w losowej kolejności, razem 2880 przebiegów; test HTTP/2 dodał 864 kolejne. Mediany mają 95-procentowe przedziały bootstrap ze stałym ziarnem. To laboratorium: jedna maszyna, localhost, bez CDN, bez obrazów i fontów, wygenerowany tekst i sztuczne 300 ms opóźnienia po stronie serwera. Ograniczanie działa per żądanie, nie na poziomie pakietów, więc czasy bezwzględne są optymistyczne; liczą się porównania. Późne kliknięcie to najlepszy przypadek dla prefetchu, a wczesne to jeden konkretny wyścig; prawdziwi użytkownicy klikają wszędzie pomiędzy. Mechanika App Shella, podwojony payload produktu i 300 ms odsłonięcia dotyczą Next.js 16.3.6 z jego wersją canary Reacta i mogą się zmienić w wydaniu poprawkowym. Wspólny szkielet jest pobierany przez adres tego linku, który router zaplanuje jako pierwszy, a ta odpowiedź niesie całą stronę dla tego adresu. Kliknięcie dokładnie w ten link nie potrzebuje żadnego żądania. Cele kliknięć wybraliśmy niżej na stronie, żeby to nie podbijało wyników Partial Prefetching. ## Dalsza lektura - [Next.js: Adopting Partial Prefetching](https://nextjs.org/docs/app/guides/adopting-partial-prefetching): Jak działa App Shell i jak przenosić trasy jedna po drugiej. - [Next.js: Optimizing prefetching](https://nextjs.org/docs/app/guides/optimizing-prefetching): Prefetch per link przez prefetch={true} i kiedy go używać. - [Next.js: prefetchInlining](https://nextjs.org/docs/app/api-reference/config/next-config-js/prefetchInlining): Co łączy inlining i dlaczego domyślne ustawienie pasuje większości aplikacji.