Some Chat Widgets Weigh 750KB. Yours Might Be One Of Them

On this page
Nobody Ever Checks This
You spent a week compressing images. You argued with a designer about a web font. You moved to a faster host and felt smug about it for a month.
Then you pasted a chat widget script above the closing body tag and went to lunch.
That script might be shipping more JavaScript than every other thing on your page combined. And almost nobody checks, because chat widgets feel small. They are a little bubble in the corner. How heavy could a little bubble be?
Pretty heavy, as it turns out.
The Actual Numbers
DebugBear ran a proper study on this, testing chat widgets in isolation to see what each one costs. The results are worth sitting with for a second.
The heaviest widgets, and this includes some very well known names, ship between 500KB and 750KB of JavaScript. Not total page weight. Just the chat widget. Just so a bubble can sit in the corner and wait for somebody to click it.
The blocking time is the part that really matters though. Those heavy widgets add somewhere in the region of 300 to 600 milliseconds of main thread blocking. That is time your browser spends parsing and executing chat code instead of responding to the human being who is trying to tap a button.
Half a second does not sound like much written down. On a mid range Android phone on a normal mobile connection, half a second of blocked main thread is the difference between a page that feels instant and a page that feels broken.
Here is the part of their data that made me wince. These are download sizes and CPU time for widgets you have definitely heard of:
| Widget | Download size | JS CPU time | Chat visible after |
|---|---|---|---|
| Zoho Desk | 67 KB | 259 ms | 3.3s |
| Crisp | 155 KB | 311 ms | 5.4s |
| Tidio | 208 KB | 540 ms | 5.3s |
| Intercom | 301 KB | 514 ms | 5.5s |
| LiveChat | 385 KB | 328 ms | 5.7s |
| Olark | 405 KB | 778 ms | 7.3s |
| Zendesk | 533 KB | 991 ms | 9.3s |
| Freshchat | 564 KB | 361 ms | 2.8s |
| Tawk.to | 749 KB | 645 ms | 3.5s |
Read that Zendesk row again. Nine point three seconds before the chat is even visible, and 991 milliseconds of CPU time to get there. Their widget is roughly 2.3 megabytes once the browser unzips it.
And the funniest entry on that list is tawk.to at 749 KB, because tawk.to is the one everybody installs specifically because it is free. It is free in money. It is not free in performance.
Credit where it is due though. Intercom noticed this about themselves and wrote publicly about cutting 400 KB out of their messenger bundle, which they reckoned saved up to five seconds on a slow connection. Good on them, genuinely. The point is that it took deliberate engineering effort to fix, and most vendors never bother.
Why Widgets Get So Fat
It is not incompetence. It is accumulation.
A chat widget starts life as a message box. Then somebody adds emoji picking. Then file uploads. Then a knowledge base search. Then video calling, screen sharing, co browsing, product tours, surveys, an analytics layer, six integrations, a chatbot builder runtime, and a framework to hold all of it together.
Every one of those features ships to every visitor. Including the visitor who never opens the chat. Including the visitor on a train with two bars of signal who just wanted to read your pricing page.
You are paying the bandwidth cost of a video calling feature that you have never used and did not know existed. That is the deal.
How To Check Yours In Two Minutes
Right, enough theory. Go look at your own site. This is genuinely quick.
- Open your site in Chrome.
- Press F12 to open DevTools, then click the Network tab.
- Click the JS filter so you are only looking at JavaScript.
- Reload the page.
- Click the Size column to sort biggest first.
Now look for your chat vendor. The domain name is usually a dead giveaway. Add up everything that belongs to them.
Two things to keep in mind while you read that number. First, the Size column shows what came over the wire, which is compressed. The uncompressed number your browser actually has to parse is often three or four times bigger. Second, some widgets load a small script first that then quietly pulls in a much larger one, so watch for a second wave of requests a moment after the page settles.
If you want the harsher version, run Lighthouse on mobile with throttling on, then disable the widget and run it again. Compare the two Total Blocking Time numbers. That difference is the tax.
The Score That Actually Bites You
Google measures something called Interaction to Next Paint. Put simply, it tracks how long your page takes to visually respond after somebody taps or clicks something.
The reason chat widgets hurt here specifically is timing. They tend to initialise right around the moment a real person starts trying to interact with the page. You scroll, you go to tap a link, and at that exact instant the browser is busy setting up a chat session, checking for an existing conversation, and rendering a bubble you did not ask for.
Your tap goes into a queue. The page feels sticky. The user does not know why and does not care why. They just think your site is slow.
And this is a ranking factor now, so it is not purely an aesthetics argument. A widget that pushes your INP over the threshold on mobile is costing you positions.
What To Do About It
You have three options really, in increasing order of effort.
Option one, load it late
The easiest win by a mile. Do not let the chat script load in the initial burst. Defer it until the page is interactive and everything important has painted.
If you are on Next.js, the documented approach is the Script component with the lazyOnload strategy. That tells the browser to wait until the browser is idle before fetching it, which is exactly right for chat. Nobody has ever opened a chat widget in the first 200 milliseconds of a page load. Nobody.
import Script from 'next/script'
<Script
src="https://cdn.example.com/w.js"
data-id="your-widget-id"
strategy="lazyOnload"
/>
On a plain HTML site, async and defer on the script tag get you most of the way there. It is one attribute and it costs you nothing.
Option two, load it on interaction
A slightly nerdier trick. Do not load the widget at all until somebody shows intent. You render a lightweight fake bubble yourself, maybe 2KB of your own code, and only when someone clicks it do you fetch the real thing.
The tradeoff is a short delay after that first click while the real widget loads. Most visitors never notice because they are still typing their first message. And you have just removed the entire cost for the ninety odd percent of visitors who were never going to chat.
Bonus, this also helps with cookie consent rules in the EU, since nothing loads until the user deliberately acts.
Option three, use something smaller
Sometimes the honest answer is that the widget is just too big and no amount of clever loading fixes it.
Here is my rough rule of thumb. Under 50KB compressed is comfortable and you can stop worrying. 50 to 150KB is fine if it loads lazily. Above 300KB you should be asking what it is actually doing, and the answer is usually a pile of features you never enabled.
For reference, our widget core sits around 15KB gzipped, and the themes load as separate chunks so you only download the one you are actually using. I mention it not to be smug but because it shows the ceiling is a choice, not a technical limit. You can build a chat widget that does the job without half a megabyte of JavaScript. People just usually do not.
The Wider Third Party Problem
Chat is rarely the only offender. It is just the one people forget about.
Go back to that Network tab and look at everything that is not your own domain. Analytics. Tag manager. Heatmaps. Two A/B testing tools because somebody trialled one and never removed it. A social proof popup. A cookie banner that somehow weighs more than your homepage.
I audited a client site last year that was carrying four hundred kilobytes of scripts belonging to services they had cancelled. The subscriptions were gone. The scripts were still there, still loading, still slowing everything down for every visitor, months later.
Nobody removes scripts. Everybody adds them. That is just how websites work.
So while you are in there, make a list of every third party domain and ask whether you can name the thing it does and the person who wanted it. Anything that fails both tests gets deleted.
One Fair Warning About Benchmarks
I should be straight with you about something.
Widget sizes change. A vendor can ship an update tomorrow that halves their bundle, or doubles it. Numbers published in any article, including this one, are a snapshot rather than a permanent fact. The DebugBear study is solid work and worth reading, but the correct move is not to trust my numbers or theirs.
The correct move is to measure your own site, with your own widget, on your own configuration. It takes two minutes. Your result is the only one that matters, because your result is the one your customers experience.
The Short Version
Chat widgets are the most commonly ignored performance problem on small business websites, mostly because they look tiny and feel harmless.
Open DevTools. Find the number. If it is above 300KB, either load it lazily, load it on click, or find something lighter. If it is under 50KB, congratulations, go fix your images instead.
How To Run The Test Properly
If you want a number you can actually trust, rather than a number that changes every time you refresh, there is a method. It takes about fifteen minutes.
Test a page that is representative, not your lightest one. Most people benchmark their homepage, which is usually the most optimised page on the site. Pick a product page or a blog post, somewhere real traffic lands.
Use mobile emulation with throttling on. Desktop numbers on a fast laptop will tell you everything is fine and they are lying to you. Your visitors are on phones on patchy connections.
Run it at least three times and take the median, never the best. Lighthouse results bounce around by a surprising amount because of network variance and whatever else your machine is doing. A single run is close to meaningless.
Then run the same three tests with the widget removed. Comment out the script, deploy to a preview URL, test again. The difference between the two medians is your real cost. That is the number to make decisions with.
One trap. Do not test in development mode if you are on a framework. Dev builds are unoptimised and enormous, and the widget will look proportionally tiny next to your unminified bundle. Always test a production build.
What Good Actually Looks Like
People ask what number they should be aiming for, so here is a rough guide based on the widget's contribution alone, not your whole page.
| Added blocking time | Verdict |
|---|---|
| Under 50 ms | Fine. Go and optimise something else. |
| 50 to 150 ms | Acceptable if it loads lazily. |
| 150 to 300 ms | Worth fixing. Change the loading strategy. |
| Over 300 ms | Loading tricks will not save you. Change tools. |
That bottom row is the honest one. There is a point where a widget is simply too heavy to rescue with clever loading, because deferring 750 kilobytes just moves the pain rather than removing it. The browser still has to download and parse all of it eventually, usually right when the user starts scrolling.
The best thing about this particular problem is how fixable it is. Most site speed work is grinding and thankless. This one is often a single attribute on a single script tag, and the improvement shows up immediately on your next Lighthouse run.
Go check. I am genuinely curious what you find.
Questions people actually ask
Does a live chat widget really slow down my website?
Yes, measurably. Independent testing by DebugBear found the heaviest widgets ship between 500KB and 750KB of JavaScript and add roughly 300 to 600 milliseconds of main thread blocking. That is enough to move an Interaction to Next Paint score from passing to failing on a mid range phone.
How do I check how heavy my chat widget is?
Open Chrome DevTools, go to the Network tab, filter by JS, reload the page, and sort by size. Your chat vendor scripts are usually obvious by their domain name. Add up the transfer sizes. It takes about two minutes and the number is often a surprise.
Will lazy loading the widget fix the problem?
It helps a lot. Loading the widget after the page is interactive means it stops competing with your actual content for the main thread. It does not reduce the total bytes, but it moves the cost to a moment where users are less likely to notice.
What is a reasonable size for a chat widget?
Under about 50KB compressed is comfortable. Between 50KB and 150KB is acceptable if it loads lazily. Anything above 300KB should have a very good reason for existing, and most of the time that reason is features you never turned on.