# third-party-web: measuring who is slowing the web down

> third-party-web is a dataset that attributes the execution time of JavaScript on the web to the companies behind the scripts, built from the monthly HTTP Archive crawl of around four million sites, queried in BigQuery, and published both as a report and as an npm module that maps a script URL to its owner. It suits anyone making decisions about which third parties to include, and its numbers are a monthly population snapshot rather than a measurement of your traffic.

**patrickhulce/third-party-web** — Data on third party entities and their impact on the web.

- Repository: https://github.com/patrickhulce/third-party-web
- Website: https://www.thirdpartyweb.today/
- Stars: 1,109 · Forks: 113
- Language: JavaScript
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/patrickhulce-third-party-web

## What the project is

Third Party Web is a project of data on third party entities and their impact on the web, and the README describes itself as a summary of which third party scripts are most responsible for excessive JavaScript execution on the web today. There is a web interface at thirdpartyweb.today, and the repository holds the data, the queries and the tooling that produce it.

The goals section lists five, and they are worth reading because they define the scope precisely. The first is to quantify the impact of third party scripts on the web. The second is to identify the third party scripts on the web that have the greatest performance cost. The third is to give developers the information they need to make informed decisions about which third parties to include on their sites. The fourth is to incentivize responsible third party script behavior. And the fifth is to make this information accessible and useful.

So this is a measurement project with a policy intent. The data is public, the method is public, and the output is a list of companies ordered by how much of the web's JavaScript time they are responsible for.

The most quoted figure from the summary section is that across the top four million or so sites, around 2700 origins account for about 57 percent of all script execution time, with the top 50 entities already accounting for about 47 percent. The README's conclusion from that is blunt, that third party script execution is the majority chunk of the web today and it is important to make informed choices.

The licence is MIT, the project is by Patrick Hulce, and the last push to the repository was on 2026-09-14, with the release list showing 0.30.0 from the same day.

## The methodology, and why attribution is the hard part

The methodology section is three sentences and it explains where every number in the report comes from.

HTTP Archive is an initiative that tracks how the web is built. Every month, around four million sites are crawled with Lighthouse on mobile. Lighthouse breaks down the total script execution time of each page and attributes the execution to a URL. And this project aggregates the script execution to the origin level using BigQuery, and assigns each origin to the responsible entity.

So the chain is: a mobile crawl, a per page breakdown of script time by URL, a query that rolls the URLs up to origins, and a mapping from origins to companies.

The last step is where the difficulty lives, and the project is honest about it in the update log. A domain is not a company. One company serves its script from many domains, often on a CDN, and one domain can serve scripts for more than one company. The mapping from domain to entity is a curated data set in the repository, maintained by hand, and the categories are a classification of those entities.

That curation is the part that is neither automatable nor neutral, and it is why the update log matters so much.

## The four numbers per entity, and how to read them

The how to interpret section gives four data points for every entity, and the definitions matter because the same word can mean two different things.

Usage, the total number of occurrences, is how many scripts from their origins were included on pages. Total Impact, the total execution time, is how many seconds were spent executing their scripts across the web. Average Impact, the average execution time, is on average how many milliseconds were spent executing each script. And the category is what type of script it is.

The distinction between total and average is where the update history does its most work, and the 2019-05-13 dataset entry explains why. A shortcoming of the attribution approach was fixed, and total usage is now reported based on the number of pages in the dataset that use the third party, not the number of scripts. Correspondingly, all average impact times are now reported per page rather than per script.

The reason given is precise, and it is a good warning for anyone reading the older numbers. Previously, a third party could appear to have a lower impact or be more popular simply by splitting their work across multiple files.

The table in that entry shows what that does to the rankings, with the per script and per page figures for six entities, from Beeketing at 137 milliseconds becoming 465, to Wix going from 972 milliseconds to 5393. The entities most affected are the hosting providers that host entire pages, and the ones that perform most of their work from a single script should see little or no change.

## The category breakdown, and where the choices actually are

The report is organised by category, and the categories are the part a developer making a decision will actually use.

The list covers Advertising, Analytics, Social, Video, Developer Utilities, Hosting Platforms, Marketing, Customer Success, Content and Publishing, CDNs, Tag Management, Consent Management Provider, and a Mixed or Other bucket. Within each category the third parties are ranked from first to last based on the average impact of their scripts.

The README's comment on this is the practical argument for the whole project. Perhaps the most important comparisons lie here. You always need to pick an analytics provider, but at least you can pick the most well-behaved analytics provider.

That is the point of the categories. The top of the list by total impact is dominated by advertising, and that is not a choice, because advertising is the business. The categories are where a choice exists, and the ranking within a category is the actionable part.

The categories also changed over time as the data was refined. In the 2019-03-01 dataset, almost 2000 entities were tracked across more than 3000 domains, and tag managers were split out into their own category since they represented such a large percentage of the Mixed or Other bucket. In the 2019-05-06 dataset, Google Ads clarified that one of its hostnames serves more ad scripts than generic tag management, and it was reclassified accordingly, which dropped the overall tag management share considerably back down to its earlier position.

Both changes move numbers between buckets, which is exactly why a reader has to know which dataset they are looking at.

## The npm module, and the export aliases

The entity classification data is published as an npm module, which is what makes the project usable in a build rather than only readable in a report.

```js
const {getEntity} = require('third-party-web')
const entity = getEntity('https://d36mpcpuzc4ztk.cloudfront.net/js/visitor.js')
console.log(entity)
//   {
//     "name": "Freshdesk",
//     "homepage": "https://freshdesk.com/",
//     "category": "customer-success",
//     "domains": ["d36mpcpuzc4ztk.cloudfront.net"]
//   }
```

So you hand it a script URL and it tells you the company, their homepage, their category and the domains the entity is known to serve from. That is enough to build a report, a lint rule or a budget check over your own page.

The package manifest shows the export aliases, and they are the interesting part. There is a subset that excludes stats, one for HTTP Archive without stats, and one for HTTP Archive. Each is a separate entry point into a subset of the data, which is a sensible way to let a consumer take the classification without taking the measurements, or take the measurements from the specific crawl the data was derived from.

The build scripts show how the pieces are assembled. The build converts the entities database, generates a canonical domain CSV, builds the per entity JSON files, generates the SQL, and then generates the export aliases. The start script merges the origins with the entities and creates the Markdown that the README and the site are built from, and there is a separate script for the automated update from the HTTP Archive data.

The package is published with provenance enabled and uses semantic-release for versioning, so the npm version and the git tags move together.

## The update log is a record of measurement changes

The updates section is the part of this project I would read first, and it is unusual in that it documents changes to the measurement rather than to the code.

The 2024-07-01 entry is about the classification. Some third parties use a dynamic subdomain to serve their main script on websites, and those subdomain scripts are saved in an observed domains file as the result of one query, but analysing the HTTP Archive database found a lot of them are ignored because of their number of occurrences, less than 50. So a new query was created to keep observed domains with an occurrence below 50 only if the entity they map to, based on the entity data, has a total occurrence greater than 50.

The 2021-01-01 entry is about the crawler. A change in the HTTP Archive measurement temporarily disabled site isolation, with out-of-process iframes, so all of the third parties whose work previously took place off the main thread is now counted on the main thread and thus appears in the stats. The README notes this is most evident in the change to Google owned properties such as YouTube and Doubleclick, whose complete cost is now captured.

The 2019-02-01 entry shows the other direction, where WordAds reduced its impact from about 2.5 seconds to about 200 milliseconds on average, and a few entities show considerably less data that cycle, possibly because they added new hostnames that are not yet identified or because the basket of sites in HTTP Archive has shifted.

The pattern across all of these is that the numbers move when either the measurement or the attribution changes, not because a vendor suddenly got slower. Any figure quoted from this project needs its dataset date attached to it, and the 2024-07-01 change is the one to check first if the entity you are looking at is missing.

## The limits, and what it is not

Three boundaries are worth keeping in mind.

The first is that this is a population snapshot, not your measurement. It tells you what four million crawled sites did on mobile in a given month. Your traffic, your devices and your users are not that population, and the third parties that dominate the crawl are the ones popular enough to appear in it. For a site with a niche audience, the ranking can be completely different, and the right way to use this data is to pick well-behaved vendors from the category table, not to look up your own vendors and hope.

The second is the cadence and the coverage. The crawl is monthly and on mobile, so a regression in a vendor's script that affects only desktop browsers will not show up, and a change that appears in the data may be a change in the crawl rather than in the vendor.

The third is the attribution, which is curated by hand and therefore subject to the classifier's judgement. The 2024 entry about dynamic subdomains is an admission that the classification is an ongoing task with known gaps, and a domain that is not in the data is invisible rather than counted as unknown.

What the project does well is make the population level picture legible, which is a service that no single site can provide for itself. The companion document in the repository, a file about facades, appears to be the project's own catalogue of the services that front another company's product on a page, which is the same attribution problem seen from the other side: a script that is really a customer's code, served under a platform's domain.

## Conclusion

Adopt third-party-web if you are choosing third party scripts and want population level evidence rather than a measurement of your own site, because the per entity impact numbers and the category breakdown answer the question of which vendor to drop. Do not treat the numbers as a measurement of your pages, since they come from a monthly mobile crawl of the wider web and they change when the measurement changes. Before you quote a figure, check the update log, because several of the headline numbers moved when the attribution method or the crawler changed.

## FAQ

### What is third-party-web?

It is a dataset of third party entities and their impact on the web, a summary of which third party scripts are most responsible for excessive JavaScript execution. The data is published as a report on a web interface and as an npm module that maps a script URL to the company behind it.

### How is the third-party-web data collected?

HTTP Archive crawls around four million sites every month with Lighthouse on mobile, Lighthouse attributes the total script execution time of each page to a URL, and the project aggregates that to the origin level with BigQuery and assigns each origin to the responsible entity.

### What do usage, total impact and average impact mean in third-party-web?

Usage is the total number of occurrences of their scripts on pages, total impact is the seconds spent executing their scripts across the web, and average impact is the milliseconds spent per script. Since the 2019-05-13 dataset, usage is counted per page rather than per script, so a vendor that split its work across files no longer appears less popular.

### How do I look up which company owns a script URL?

The npm module exposes a getEntity function that takes a script URL and returns an object with the name, homepage, category and the domains of the entity, for example returning Freshdesk for a script served from a cloudfront domain. Export aliases are provided for subsets of the data.

## Sources

- [License: MIT](https://github.com/patrickhulce/third-party-web/blob/master/LICENSE)
- [patrickhulce/third-party-web on GitHub](https://github.com/patrickhulce/third-party-web)
- [Project website](https://www.thirdpartyweb.today/)
- [README](https://github.com/patrickhulce/third-party-web/blob/master/README.md)
- [Releases](https://github.com/patrickhulce/third-party-web/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/patrickhulce-third-party-web
