User Tools

Site Tools


programming:interaction

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
programming:interaction [2025/03/19 08:51] – Links and references karelkubicekprogramming:interaction [2026/08/27 12:39] (current) – Reviewer 4 (generic): add 'Interacting is not free' — click fraud, form side effects, load multiplied by 3x, and the visibility trade-off — and a Monday-morning default design; replace the unaudited 'none of them justified anywhere' with the measured just karel.kubicek.claude
Line 1: Line 1:
-====== Interaction with website ======+====== Interaction with Websites ======
  
-<wrap todo>This page only contains notes</wrap>+''page.goto(url)'' returns, and then you have a decision to make. Almost every result a web measurement publishes is a count of things observed **after** that moment — cookies set, requests issued, scripts loaded, banners shown — and every one of those counts depends on what the crawler did next. Load and leave? Follow a link? Follow twenty? Scroll to the bottom? Click the button that loads the ads? Log in?
  
-Topics to cover (in separate pages):+The literature is unusually explicit about the first of those and almost silent about the rest. This page is about all of them: how deep into a site to go, which pages to pick when you go deeper, what to do on a page once you are there, and how to report the choice so a reviewer can tell what your number is a count of.
  
-  * Input into website forms +Neighbouring pages own the pieces that are decisions in their own right: what to do with the cookie banner is [[Privacy:Consent|Granting Consent to Websites]]; whether the profile survives between visits is [[Programming:Stateful Stateless|Stateful and Stateless Crawling]]; getting past login is [[Programming:Registration|Automating Login and Registration]]; the libraries that give you the click are [[Programming:Crawler|Comparison of Crawling Libraries]]Which //sites// you visit is [[Design:Website selection]] — this page starts once that list exists.
-  * [[privacy:consent|Interacting with consent]] +
-  * [[programming:stateful_stateless|Stateful and stateless crawling]] +
-    * Urban et al. {[urban2020beyond]} studied crawling only index pages vs crawling multiple subpages of website, showing significant increase in third-party requests and cookies when you browse also subpagesFrom 10 visited subpages is increase small.+
  
-/* +<WRAP important> 
-This is a comment not visible on the page. It outlines the syntax (for more, go to https://measuretheweb.org/wiki/syntax), especially that related to bibliography. Remove it once you created the page. If you use any citations (documented at bottom), keep the References section.+Three things this page exists to stop you getting wrong.
  
-===== Header Level ===== +  - **"We crawled 10,000 websites" is not a measurement unit.** A website is not a page. Of the **857 papers in [[literature:corpus|this corpus]] that ran an automated web crawl of the web**, **417** give a value on the site-depth axis, and **155 of those 417 (37.2%)** stayed on the landing page. The landing page is a systematically atypical page — see [[#Deeper is not simply more]]. 
-==== Header Level ====+  - **Ten subpages is the folk default and it is not where the curve flattens.** The median stated ''subpagesPerSite'' in this corpus is **10**. The one paper that actually measured where the increase stops found cookies stabilising **after 100 subpages**, not ten {[urban2020beyond]}. See [[#Where the increase stops]]. 
 +  - **Navigating is not interacting.** A great deal of what a privacy measurement counts — lazily-loaded ad slots, content behind a tab or an accordion, anything a form submission triggers — does not exist at ''load''. In the corpus, **69 of 857 web crawls (8.1%)** describe scrolling in their own methods and **28 (3.3%)** describe filling a form. (Loosen the pattern to any mention anywhere in the paper and it is 120 and 59 — still small.) The measured ladder in [[#What a strategy can and cannot see|the probe below]] shows a beacon that only a scroll reveals and another that only a click reveals — on a fixture built to have them, but built that way because real pages are. 
 +</WRAP>
  
-=== Links ===+===== What to Read First =====
  
-External links are recognized automaticallywww.google.com, but if you want a link text: [[http://www.google.com|This Link points to google]].+  * **On Landing and Internal Web PagesThe Strange Case of Jekyll and Hyde in Web Performance Measurement** {[aqeel2020_landing]}, IMC 2020 — the paper that made "we used a top list, so we crawled landing pages" a stated limitation rather than an unexamined defaultIt reviews 119 web-performance papers and concludes that about two-thirds would need revising to apply to internal pagesRead it even if your topic is privacy, not performance: the argument is about top lists, and every privacy crawl uses one. 
 +  * **Beyond the Front PageMeasuring Third Party Dynamics in the Field** {[urban2020beyond]}, TheWebConf 2020 — the privacy-side counterpart, published the same year, and the only paper here that measures **how many** subpages you need. Read it for the pre-study in §4, not only for the headline. 
 +  * **Apophanies or Epiphanies? How Crawlers Impact Our Understanding of the Web** {[ahmad2020_apophanies]}, TheWebConf 2020 — what changes when you change the instrumentRead it before you argue that your crawler choice does not matter. 
 +  * **Towards Realistic and Reproducible Web Crawl Measurements** {[jueckstock2021_realistic]}, TheWebConf 2021 — realism as an axis you can rank designs on, rather than a limitation-section apology. 
 +  * **The Representativeness of Automated Web Crawls as a Surrogate for Human Browsing** {[zeber2020representativeness]}, TheWebConf 2020 — the size of the gap between what your crawler sees and what a person sees, measured against telemetry from more than 50,000 opt-in Firefox users. 
 +  * **Reproducibility and Replicability of Web Measurement Studies** {[demir2022_reproducibility]}, TheWebConf 2022 — the checklist form of everything on this page, and the one to cite when a reviewer asks why you reported a configuration detail.
  
-Internal links are created by using square brackets. You can either just give a [[pagename]] or use an additional [[pagename|link text]].+===== Four Axes, Not One =====
  
-=== Lists ===+"Interaction" is four independent decisions that papers routinely collapse into one sentence. Separating them is the whole of the reporting problem.
  
-Lists and their levels are decided by indentation (2 spaces = 1 level)+^ Axis ^ The question ^ Where it is decided ^ Where this corpus records it ^ 
 +| **Depth** | how far below the site root does a visit go | your crawl loop | ''crawlConfig.interactionDepth'', ''subpagesPerSite''
 +| **Selection** | //which// pages below the root | your link-picking rule | nowhere — it lives only in prose | 
 +| **On-page action** | scroll, click, hover, type, wait | your per-page script | nowhere — full-text sweep only | 
 +| **Identity** | consent choice, login, registration | before or during the visit | ''crawlConfig.consentAction'', ''crawlConfig.authentication'' |
  
-  - this is 1item +The two middle rows are the ones with no schema field anywhere, in this corpus or in the reporting checklists, and they are exactly the two that decide whether your crawl saw the ad.
-  - 2. item +
- - nested a. item +
-  * bullet-point item+
  
-=== Code ===+==== Depth has more than three positions ====
  
-For a short inline monospace, use ''double quote''For proper code (but in a separate paragraph), use ''<code LANG>'':+The extraction's enum has five values and only three of them answer "how far into the site". Read against the papersown text, the fourth is a different design entirely and is kept out of every depth figure on this page.
  
-<code python+^ Value ^ What it means ^ Web crawls in the corpus ^ 
-string = "World+| ''landing-page-only'' | one page per site, the root | 155 | 
-print(f'Hello {string}')+| ''landing-plus-subpages'' | the root plus a bounded set of pages below it | 137 | 
 +| ''deep-crawl'' | traverse until a budget or a frontier runs out — usually of //one// application, forum or marketplace, not of a ranked list | 125 | 
 +| ''single-target-page'' | one specific URL per target that is **not** the site root: a phishing URL, a product page, a trace-collection target, an API endpoint | 285 | 
 +| ''not-stated'' | — | 136 | 
 + 
 +''single-target-page'' is the largest single value, and treating it as a depth answer is the easiest mistake to make with this data. It fires on website-fingerprinting trace collection, phishing-blocklist monitors, search-result scrapes and dashboard pulls. Those crawls have a page list, not a site list, so "how deep did you go" does not apply to them. **Every percentage of the depth //distribution// on this page has a denominator of 417, not 857 and not 5,859.** (Reporting rates and on-page-action shares are of 857; each table says which.) 
 + 
 +There is also a terminology trap that a keyword search will not survive: in the phishing, malvertising and spam literature **"landing page" means the destination of a redirect or ad click**, not the root of a site. The same two words name the thing this page is about and the thing that page is about. 
 + 
 +===== How Deep the Field Actually Goes ===== 
 + 
 +Depth is the **best-reported** crawl-configuration field in this corpus, though only just: of the 1,120 crawling papers, 75.1% state a depth against 69.6% for authentication — and then the field falls off a cliff. 
 + 
 +^ ''crawlConfig'' field ^ Papers stating it ^ Share of 1,120 crawling papers ^ 
 +| ''interactionDepth'' | 841 | 75.1% | 
 +| ''authentication'' | 779 | 69.6% | 
 +| ''browsers'' | 529 | 47.2% | 
 +| ''consentAction'' | 349 | 31.2% | 
 +| ''statefulness'' | 219 | 19.6% | 
 +| ''headless'' | 140 | 12.5% | 
 + 
 +That is worth knowing before you decide depth is not worth a sentence: it is the one crawl-configuration choice the field already has a habit of writing down, so omitting it stands out. 
 + 
 +^ Bucket ^ Web crawls ^ States a depth ^ On the site-depth axis ^ Of those, went beyond the landing page ^ Gives a subpage count ^ 
 +| 2010–2013 | 80 | 67 (83.8%) | 35 | 27 (77.1%) | 8 (10.0%) | 
 +| 2014–2017 | 130 | 109 (83.8%) | 57 | 35 (61.4%) | 11 (8.5%) | 
 +| 2018–2021 | 241 | 198 (82.2%) | 121 | 72 (59.5%) | 37 (15.4%) | 
 +| 2022–2024 | 253 | 207 (81.8%) | 125 | 82 (65.6%) | 33 (13.0%) | 
 +| 2025–2026((Provisional: CCS 2026 and IMC 2026 have not been held, and IEEE S&P 2026 and TheWebConf 2026 are incompletely indexed in the abstract source the corpus selects on, so the bucket under-represents those venue-years by construction.)) | 153 | 121 (79.1%) | 79 | 46 (58.2%) | 15 (9.8%) | 
 + 
 +Two readings, and they point in different directions. 
 + 
 +The good news: **about four in five web crawls say something about depth**, and that has been roughly true since 2010 — though the direction is very slightly down, from 83.8% in the first bucket to 79.1% in the last, which [[Programming:Stateful Stateless|the statefulness page]] reads as the one crawl-configuration field whose reporting rate has //declined//. Compare it with statefulness, which 19.6% of crawling papers state ([[Programming:Stateful Stateless#Reporting has not improved in sixteen years|the flattest field in the schema]]). 
 + 
 +The bad news: the second and third numbers barely move. Sixteen years after the field started worrying about this, **the share that goes beyond the landing page is not rising**, and **only 104 of 857 web crawls (12.1%) put a number on how many subpages** — 102 of the 417 on the depth axis, 24.5%. "We also crawled subpages" is not a reproducible statement, and it is the commonest form the claim takes. 
 + 
 +<WRAP important
 +**The 62.8% is an upper bound, not a level.** Of the 417 papers on the site-depth axis, 262 (62.8%) went beyond the landing page. But a paper that crawled deeper has a reason to describe its traversal, and a paper that did not may simply have written "we visited the top 10k websites" and left it there. The 136 ''not-stated'' papers are missing from the denominator, and they are much more likely to be landing-only than deep. Read the ratio as //"among papers that say"//, never as //"among crawls"//
 +</WRAP> 
 + 
 +==== Which numbers people pick ==== 
 + 
 +Of the 104 web crawls that state a subpage count, the distribution is bimodal, and the two modes are two different research designs. 
 + 
 +^ Subpages per site ^ Papers ^ Share of 104 ^ 
 +| 0 (landing page only) | 4 | 3.8% | 
 +| 1–4 | 29 | 27.9% | 
 +| 5–9 | 15 | 14.4% | 
 +| 10–19 | 21 | 20.2% | 
 +| 20–49 | 16 | 15.4% | 
 +| 50–99 | 2 | 1.9% | 
 +| 100 or more | 17 | 16.3% | 
 + 
 +Median 10, and it does not settle: per four-year bucket the median runs 5, 5, 10, 15, 5 on 8, 11, 37, 33 and 15 papers, which is small-sample noise rather than a trend. The five commonest values overall are 5 (14 papers), 3 (12), 10 (12), 1 (11) and 20 (8) — all small and all round. Whether they are //justified// is harder to establish than it looks, and a full-text sweep over the 104 puts an upper bound on it: **13 (12.5%)** cite Urban et al. anywhere in the paper, **12 (11.5%)** cite Aqeel et al. or Hispar, **18 (17.3%)** use the words //pilot// or //pre-study//, and **10 (9.6%)** use //saturation//, //diminishing returns// or //plateau// anywhere at all. Every one of those is an upper bound on justifying //this// choice, because a citation in related work is not a justification of a number in the methods section. The tail above 100 is not "more of the same": those are deep crawls of a single application or forum (100, 200, 300, 500, 1,000 and 2,000 pages per target all appear), where the population is one site and the pages are the sample. 
 + 
 +The honest summary is that **the field converged on "a handful of subpages" without measuring whether a handful is enough**, and the one paper in this corpus that did measure says it is not. 
 + 
 +===== Deeper is Not Simply More ===== 
 + 
 +This is the part that is easy to get backwards. Crawling deeper does not uniformly increase every privacy metric, and two of the field's most-cited results on the question disagree in direction because they measure different quantities. 
 + 
 +==== Urban et al.: subpages carry more ==== 
 + 
 +Urban et al. crawled the top 10,000 websites (TLD+1) with OpenWPM, visiting the landing page **and 100 subsites** of each, from several regions {[urban2020beyond]}: 
 + 
 +  * **cookies: +36%.** "subsites set considerably more (36 %) cookies than the respective landing pages. On average, 55 cookies were set when loading a landing page while 78 were set when a subsite was accessed." 
 +  * **trackers: about +6%**, matched against EasyPrivacy — and **2.5% of sites** showed tracking **only** on subsites, so a landing-only crawl records them as untracked. 
 +  * **device fingerprinting: +25%**, detected via the Fingerprint2 library, which appeared on only 0.15% of landing pages. 
 + 
 +Their conclusion is a methodological instruction, not a finding about the web: a landing-page study "is only able to measure a lower bound"
 + 
 +==== Aqeel et al.: landing pages are heavier, internal pages are wider ==== 
 + 
 +Aqeel et al. compared the landing page against internal pages for 1,000 sites and reached results that read as the opposite until you notice the metric {[aqeel2020_landing]}. Per page, the landing page is the bigger, busier one: 
 + 
 +  * landing pages are on average **34% larger** than internal pages (geometric mean of per-site ratios); 
 +  * at the 80th percentile, internal pages carry **20 tracking requests** and landing pages **28** — measured by counting requests the Brave adblock library plus EasyList would have blocked; 
 +  * in about **10%** of sites, internal pages have **no** trackers while the landing page does. 
 + 
 +But the **union across internal pages is wider than any single page**: 
 + 
 +  * in the median, internal pages collectively fetch content from **18 third-party domains that never appear on the landing page**; for 10% of sites, **80 or more**; 
 +  * of 200 sites checked for header bidding, **17** had it on the landing page and a further **12 only on internal pages**; 
 +  * 36 of the 1,000 sites served their landing page over plain HTTP, but among the sites whose landing page was secure, **170 had at least one HTTP internal page**. 
 + 
 +So the two results are compatible, and together they are more useful than either alone: 
 + 
 +<WRAP important> 
 +**Per-page density and union coverage move in opposite directions.** The landing page is the most heavily instrumented //single// page on a typical site. The set of internal pages reaches //more distinct// third parties. Which of those your number is a count of decides whether crawling deeper raises it or lowers it — and it is not something any of the reporting checklists asks for, so it is on you to say it. A per-page mean is not a prevalence, and a prevalence over sites is not a per-page mean. 
 +</WRAP> 
 + 
 +Aqeel et al. also put a number on the scale of the problem in the surrounding literature: of **119** publications they reviewed at IMC, PAM, NSDI, SIGCOMM and CoNEXT between 2015 and 2019, **41 (34.5%) need no revision, 48 (40.3%) a minor revision and 30 (25.2%) a major one** to apply to internal pages. 
 + 
 +==== And the effect is not only about depth ==== 
 + 
 +Khaleesi ran the same Alexa top-10K under the same cookie policy in two configurations — a plain homepage crawl, and an "interactive" crawl that additionally navigated to random internal pages by clicking on iframes and anchor tags {[iqbal2022_khaleesi]}: 
 + 
 +^ Configuration ^ Requests ^ Request chains ^ 
 +| cookies allowed, homepage | 192,038 | 76,816 | 
 +| cookies allowed, interactive | 575,550 | 229,151 | 
 + 
 +That is **3.0× the requests and 3.0× the chains from the same site list**. And the difference is not only volume: 302 redirects make up **42.91%** of advertising-and-tracking redirect requests in the homepage crawl against **28.56%** interactive, and **51.32%** of such requests navigate to a new domain in the homepage crawl against **47.49%** interactive. A classifier trained on one and applied to the other is being applied off-distribution. 
 + 
 +Two smaller replications in the same direction: 
 + 
 +  * Musch and Johns swept for JavaScript anti-debugging over front pages plus **three random internal subpages** {[musch2021_debug]}: "we can see that visiting subpages did indeed significantly increase the prevalence by about 17% compared to only crawling the front pages". The denominator is 206,676 sites with an indicator, of which **30,494 showed it only on a subpage**. And the aggregate hides the variance: per technique the subpage-only increase runs from **+18%** and **+19%** for the two commonest indicators up to **+80%** for triggered breakpoints — so how much depth matters depends on which behaviour you are counting, not just on the depth. 
 +  * Lauinger et al. state the other side plainly, and give the reason a landing-only design is often the right one: "We only crawl the homepage of each visited site due to the presence of many sites that thwart deeper traversal by requiring log-ins." {[lauinger2017_thou]} 
 + 
 +===== Where the Increase Stops ===== 
 + 
 +The most useful number in this literature is buried in a pre-study. Urban et al. selected 100 random sites from the top 1,000 and crawled **25, 50, 75, 100, 250, 500 and 1,000 subsites** of each, then looked at where the cookie count stopped growing {[urban2020beyond]}: 
 + 
 +> the mean amount of accessed/set cookies stabilizes around 50 (SD: 100; median at 12) after visiting 100 subsites 
 + 
 +That is the sentence to cite when a reviewer asks why you chose your number, and it is **an order of magnitude above the field's median of ten**. Their main crawl accordingly uses 100 subsites per site, not a handful. 
 + 
 +Note two boundaries before you copy the 100 across: 
 + 
 +  * It is a **cookie-count** saturation curve on the **top 1,000** sites in 2019–2020. A different metric (distinct third-party domains, ad slots, fingerprinting scripts) and a different rank band will have a different curve — and unpopular sites have fewer subpages to give. 
 +  * The curve is about **how many**, not **which**. Saturating the count says nothing about whether you reached the pages that matter for your question. 
 + 
 +A note this page has to make, because the previous version of it carried the opposite claim: the earlier text here said the increase becomes small after about **ten** subpages. That number is not in the paper. The pre-study's smallest step is 25, and its stated stabilisation point is 100.((Checked against ''data/fulltext/2020/WWW/beyond-the-front-page-.../paper.cols.txt'' on 2026-08-27; see [[provenance:programming:interaction]].)) 
 + 
 +===== Choosing Which Subpages: a Sampling Decision in Disguise ===== 
 + 
 +There is no field for this in any schema and no convention in the literature, and it changes results more than the count does. Five rules are in use: 
 + 
 +^ Rule ^ What it gives you ^ What it biases towards ^ Seen in ^ 
 +| **First //N// same-origin links in DOM order** | cheap, deterministic, reproducible from the page alone | navigation chrome: //About//, //Contact//, //Privacy// — the least commercial pages on the site | HTTP Archive's crawler (below) | 
 +| **Random //N// first-party links** | avoids the nav bias; needs a seed to be reproducible | pages reachable in one hop; misses everything behind a search box or a paginated feed | {[urban2020beyond]}, {[iqbal2022_khaleesi]}, {[musch2021_debug]} | 
 +| **Random //N// with an exclusion list** | drops the pages you know are unrepresentative | your exclusion list becomes part of the method and must be published | {[reitinger2024_creepy]}: "We added ten random sub-pages per domain, filtering to exclude auxiliary pages like privacy policies or contact pages."
 +| **Search-engine "popular" pages** | pages real users actually land on | English-language and search-visible pages; costs money per query; needs a search API | {[aqeel2020_landing]} (Hispar) | 
 +| **Clickstream traversal** — click a real element, then continue from wherever you land | closest to a session; the same path can be replayed across arms | whatever is clickable and static; the authors of the clearest example say so themselves | {[lin2024_browsing]} | 
 + 
 +That last one is worth quoting, because it is the rare case of a paper naming its own selection bias precisely {[lin2024_browsing]}: 
 + 
 +> our dataset is biased towards static inner pages which may cause us to underestimate the impact cookies have on website appearance, as we are less likely to explore the more dynamic areas of a website 
 + 
 +Two further points a reviewer will raise: 
 + 
 +  * **Same-origin is not the same as first-party.** A link to ''shop.example.com'' from ''example.com'' is same-site and cross-origin; a link to ''example.co.uk'' is neither. Say which test you used, and say whether you used the Public Suffix List. 
 +  * **The frontier is state-dependent.** Which links exist on the landing page depends on your consent choice, your geolocation, your logged-in state and the hour. Two arms of an experiment that each harvest their own links are not visiting the same pages. Harvest the link set **once**, freeze it, and replay it in every arm — that is what Urban et al. do (collect first-party hyperlinks one day before the first measurement, then reuse the same list across regions), and what Lin et al. do by replaying the same CSS selectors across all three crawl groups. 
 + 
 +==== The one page list that included internal pages is gone ==== 
 + 
 +Aqeel et al. shipped **Hispar**: a top list of complete URLs rather than domains — around 2,000 sites, one landing page and up to 49 internal pages each, 100,000 URLs, refreshed weekly, with the internal pages discovered through Google ''site:'' queries {[aqeel2020_landing]}. 
 + 
 +**Do not plan a study around it.** Checked on 2026-08-27: ''hispar.cs.duke.edu'' no longer resolves at all; the last Internet Archive capture that returned any content is 2024-11-16, and the last capture of any kind is a 403 on 2024-12-03; the generator at ''github.com/waqaraqeel/hispar'' was last pushed on 2020-10-27 and ''lit_grabber'' on 2020-05-26. Its bootstrap list, the Alexa Top 1M, was itself retired in 2022, so even the generator cannot be run as written. The idea outlived the artefact. 
 + 
 +**What exists instead, and what it gives you.** Since April 2022 the HTTP Archive crawls **one secondary page per site** alongside the root, and both are in the public BigQuery dataset with ''is_root_page'' and ''root_page'' columns to tell them apart.((HTTP Archive BigQuery reference, //Pages table//, ''har.fyi/reference/tables/pages/'': "Pages are tested on a monthly basis and as of April 2022, both the root page and one secondary page are tested." Checked 2026-08-27. Note that ''httparchive.org/faq'' still says the opposite — "The HTTP Archive examines each URL in the list, but does not crawl the website's other pages" — and is stale.)) Read the selection rule before you use it as an internal-page sample: in the crawl controller, ''MAX_DEPTH = 1'' and ''MAX_BREADTH = 1'', and the child job is the **first** link on the page whose hostname equals the parent's, whose extension is not an image, PDF or archive, and which has not already been visited.((''github.com/HTTPArchive/crawl'', files ''crawl.py'' and ''crawl_pubsub.py'' at commit ''4b83ac0'' (2025-08-20). Checked 2026-08-27.)) That is the //first link in DOM order// rule from the table above, with all of its bias: on most sites it is a navigation item. It is a real internal page and it is not a random one. 
 + 
 +===== What the Crawler Does on the Page ===== 
 + 
 +Below the depth question there is a second one that no reporting checklist covers: once the page is open, does anything happen? The corpus has no field for it, so the only way to count is to sweep the full text. Every figure in this section is an **upper bound** on "the paper did this" — it counts papers with a first-person sentence matching the pattern, and "we did not scroll" matches too. 
 + 
 +^ What the paper's own text says it does ^ Papers ^ Share of 857 ^ 
 +| clicks something | 282 | 32.9% | 
 +| scrolls | 69 | 8.1% | 
 +| waits or dwells for a stated time | 56 | 6.5% | 
 +| types on the keyboard | 39 | 4.6% | 
 +| fills a form | 28 | 3.3% | 
 +| moves the mouse | 18 | 2.1% | 
 +| hovers | 14 | 1.6% | 
 +| picks links at random | 14 | 1.6% | 
 +| says it aims for human-like behaviour | 14 | 1.6% | 
 +| mentions bot or crawler detection | 61 | 7.1% | 
 + 
 +The only two rows with a clear trend across the sixteen years are **scrolling** — 2.5% of web crawls in 2010–2013 against 11.1% in 2025–2026 — and **bot detection**, which not one paper in the 2010–2013 bucket raises //in a first-person sentence// against 11.8% of the 2025–2026 bucket. (Three of those 80 papers do mention it somewhere in the text — a probe's zero is never the same as nobody.) Clicking has **not** risen: it sits between 29.9% and 43.8% in every bucket, and the //highest// value is the earliest one. Mouse movement and hovering are, and have always been, under 4%. 
 + 
 +==== What a strategy can and cannot see ==== 
 + 
 +The table below is **measured**, not recalled. A local instrumented site serves a landing page with three same-origin links; one subpage loads a beacon at page load and links onward to a page the landing page never links to; that subpage loads a second beacon only when you reach the bottom; another subpage loads a beacon only when a button is clicked. Playwright's own Chromium then visits it under six strategies. A ✓ means the strategy **observed** that third party. 
 + 
 +<code> 
 +strategy                                                             pages  t-landing  t-article   t-scroll    t-click     t-deep 
 +-------------------------------------------------------------------  -----  ---------  ---------  ---------  ---------  --------- 
 +landing page only                                                        1          ✓          ✗          ✗          ✗          ✗ 
 +landing + FIRST same-origin link (the HTTP Archive rule)                          ✓          ✗          ✗          ✗          ✗ 
 +landing + ALL same-origin links from the landing page                    4          ✓          ✓          ✗          ✗          ✗ 
 +landing + all links, and scroll to the bottom of each                    4          ✓          ✓          ✓          ✗          ✗ 
 +landing + all links, scroll, and click every button                      4          ✓          ✓          ✓          ✓          ✗ 
 +depth 2: landing, its links, and their links, with scroll and click      5          ✓          ✓          ✓          ✓          ✓ 
 + 
 +t-landing  on the landing page 
 +t-article  on one subpage, at load 
 +t-scroll   on that subpage, only after scrolling to the bottom 
 +t-click    on another subpage, only after a button click 
 +t-deep     on a page linked only from a subpage, never from the landing page 
 + 
 +Playwright 1.62.1, Chromium 151.0.7922.34, linux. Needs no network.
 </code> </code>
  
-For large code, use ''<file LANG filename>'', it will make code downloadableFor instance:+Reproduce with [[#The code|the two files below]]: the version linethe platform and the legend are printed by the script itself.
  
-<file php example.php+Read off the second row. Following the **first** same-origin link found nothing that the landing page had not already shown, because the first link in DOM order is the //About// page and the //About// page is empty of third parties. That is not a quirk of the fixture — it is what the HTTP Archive's secondary-page rule does on any site whose navigation starts with an institutional page, and it is why "we crawled a secondary page" and "we sampled an internal page" are different claims. 
-<?php echo "hello world!"; ?>+ 
 +Read off the last row. Each additional capability found exactly one thing the previous one could not, and no amount of extra depth substitutes for the scroll, nor extra scrolling for the click. **These are not degrees of the same knob.** A design that goes three levels deep without scrolling still misses everything below the fold. 
 + 
 +==== Interacting is not free, and it is not only your cost ==== 
 + 
 +Everything above says //do more//. Before you scale it to ten thousand sites, four consequences that a landing-page crawl does not have: 
 + 
 +  * **A click on an ad is an ad impression somebody pays for.** Ad clicks are billed. A crawl that clicks indiscriminately at scale generates click fraud, and the money comes out of an advertiser's budget. Reitinger et al. designed around exactly this: rather than fetch an ad's destination link — which "could charge advertisers as a higher-cost //click//" — they parse the destination out of the URL instead {[reitinger2024_creepy]}. If you must resolve where an ad goes, resolve it without clicking it. 
 +  * **A form submission has a side effect on a real system.** Filling and submitting forms at scale sends real newsletter signups, real support tickets, real account registrations and real search queries against production databases. This is why EvoCrawl's evaluation runs against **ten self-hostable web applications** — WordPress, HotCRP, Kanboard, ImpressCMS, phpBB, Humhub, GitLab and others, each shipped as a Dockerfile in the repository's ''experiments/'' folder — rather than against the live web {[guo2025_evocrawl]}. The interaction depth it achieves is only safe on a system you own. Read the [[Practices:Ethics|ethics page]] before you point a form-filler at a site list. 
 +  * **Interaction multiplies your load by more than you expect.** The Khaleesi comparison above is 3× the requests from the same list. Rate limits, politeness delays and any ''robots.txt'' policy you have should be set for the interactive figure, not the landing-page one. 
 +  * **You are more visible, and being detected is not neutral.** A crawler that clicks and scrolls looks less like a bot to a fraud model and more like a user — which is the point, and is also why the resulting impressions and clicks are harder for the site to filter out. "We made the crawler look human" and "we made our traffic indistinguishable from the traffic the site bills for" are the same sentence. 
 + 
 +None of this argues for staying on the landing page. It argues for saying, in the paper, which interactions you performed, on how many sites, and what you did to keep them from being charged for. 
 + 
 +==== The code ==== 
 + 
 +Save both files side by side; the second imports the first. 
 + 
 +<file javascript interaction_site.mjs
 +// A minimal instrumented site for the interaction probe: a landing page, three 
 +// same-origin subpages, and third-party beacons that fire under DIFFERENT 
 +// conditions. It is built to hit exactly the disagreements this page is about — 
 +// a beacon only on a subpage, a beacon only after scrolling, a beacon only 
 +// after a click, and a page only reachable two links deep. 
 +// 
 +// Third parties are served from a SECOND origin (127.0.0.2) so the crawler 
 +// counts them as third-party the way a real measurement would. 
 +// 
 +// PORTABILITY: Linux gives you the whole 127.0.0.0/8 loopback range for free. 
 +// macOS does not — binding 127.0.0.2 fails with EADDRNOTAVAIL until you add the 
 +// alias:  sudo ifconfig lo0 alias 127.0.0.2 up 
 +// (undo with `sudo ifconfig lo0 -alias 127.0.0.2`). On Windows, use WSL. 
 +import http from 'node:http'; 
 + 
 +const PAGE = (title, body) => `<!doctype html><meta charset=utf-8><title>${title}</title> 
 +<style>body{font-family:sans-serif} .tall{height:3000px}</style>${body}`; 
 + 
 +export function startSite({ port = 8231, tpPort = 8232 } = {}) { 
 +  const requests = [];               // every request BOTH origins received 
 +  const log = (origin, url) => requests.push({ origin, url }); 
 + 
 +  const first = http.createServer((req, res) => { 
 +    log('first', req.url); 
 +    const tp = (name) => `http://127.0.0.2:${tpPort}/${name}.gif`; 
 +    if (req.url === '/') { 
 +      return send(res, PAGE('landing',
 +<h1>landing</h1> 
 +<nav> 
 +  <a href="/about">about</a> 
 +  <a href="/article">article</a> 
 +  <a href="/shop">shop</a> 
 +</nav> 
 +<img src="${tp('t-landing')}">`)); 
 +    } 
 +    if (req.url === '/about') { 
 +      // A quiet subpage: no third party at all. Included so that "pick one 
 +      // subpage" can land on the page that shows you nothing. 
 +      return send(res, PAGE('about', '<h1>about</h1><p>no third parties here.</p>')); 
 +    } 
 +    if (req.url === '/article') { 
 +      return send(res, PAGE('article',
 +<h1>article</h1> 
 +<img src="${tp('t-article')}"> 
 +<a href="/comments">comments</a> 
 +<div class=tall></div> 
 +<img id=lazy alt=""> 
 +<script> 
 +  // Fires only when the bottom of the page is reached. 
 +  addEventListener('scroll', () => { 
 +    if (window.scrollY + innerHeight >= document.body.scrollHeight - 50) { 
 +      const el = document.getElementById('lazy'); 
 +      if (!el.src) el.src = '${tp('t-scroll')}'; 
 +    } 
 +  }, { passive: true }); 
 +</script>`)); 
 +    } 
 +    if (req.url === '/comments') { 
 +      // Two links deep: only linked from /article, never from the landing page. 
 +      return send(res, PAGE('comments', `<h1>comments</h1><img src="${tp('t-deep')}">`)); 
 +    } 
 +    if (req.url === '/shop') { 
 +      return send(res, PAGE('shop',
 +<h1>shop</h1> 
 +<button id=b>show offers</button> 
 +<img id=ad alt=""> 
 +<script> 
 +  document.getElementById('b').addEventListener('click', () => { 
 +    document.getElementById('ad').src = '${tp('t-click')}'; 
 +  }); 
 +</script>`)); 
 +    } 
 +    res.writeHead(404, { 'cache-control': 'no-store' }); 
 +    res.end('nope'); 
 +  }); 
 + 
 +  const third = http.createServer((req, res) => { 
 +    log('third', req.url); 
 +    res.writeHead(200, { 'content-type': 'image/gif', 'cache-control': 'no-store' }); 
 +    res.end(Buffer.from('47494638396101000100800000ffffff00000021f90401000000002c00000000010001000002024401003b', 'hex')); 
 +  }); 
 + 
 +  const send = (res, html) => { 
 +    res.writeHead(200, { 'content-type': 'text/html; charset=utf-8', 'cache-control': 'no-store' }); 
 +    res.end(html); 
 +  }; 
 + 
 +  return Promise.all([ 
 +    new Promise((r) => first.listen(port, '127.0.0.1', r)), 
 +    new Promise((r) => third.listen(tpPort, '127.0.0.2', r)), 
 +  ]).then(() => ({ requests, close: () => { first.close(); third.close(); } })); 
 +}
 </file> </file>
  
-=== Figures ===+<file javascript interaction_probe.mjs> 
 +// What does each interaction strategy actually see? Drives Playwright's own 
 +// Chromium against the local instrumented site in interaction_site.mjs and 
 +// reports, per strategy, which third-party beacons were observed. 
 +// 
 +//   npm i playwright && npx playwright install chromium 
 +//   node interaction_probe.mjs 
 +// 
 +// Read as: a ✓ means the strategy OBSERVED that third party. The fixture has 
 +// five, each reachable only under a different condition, so the table is a 
 +// direct statement of what a crawl design can and cannot see. 
 +import { chromium } from 'playwright'; 
 +import { startSite } from './interaction_site.mjs';
  
-To use floats, you have to use the ''<WRAP>'' tag. For instance, the following will create figure on the right side 50% large: +const PORT = 8231; 
-<WRAP right 50% box> +const TP = 8232; 
-{{PATH_TO_FILE|ALT_TEXT}+const ORIGIN = `http://127.0.0.1:${PORT}`; 
-<div>CAPTION</div> +const site = await startSite({ port: PORT, tpPort: TP });
-</WRAP>+
  
-*/+const BEACONS = ['t-landing', 't-article', 't-scroll', 't-click', 't-deep'];
  
-====== References ======+// Collect the third-party hostnames+paths seen during one strategy. 
 +let chromiumVersion null;
  
-/* +async function run(name, fn) { 
-To insert citationsfollow these steps:+  const seen = new Set(); 
 +  const browser = await chromium.launch(); 
 +  chromiumVersion = browser.version(); 
 +  const context = await browser.newContext(); 
 +  context.on('request', (r) => { 
 +    const u = new URL(r.url()); 
 +    if (u.hostname !== '127.0.0.1') seen.add(u.pathname.replace(/^\/|\.gif$/g, '')); 
 +  }); 
 +  const page = await context.newPage(); 
 +  const pagesVisited = await fn(page); 
 +  await page.waitForTimeout(300); 
 +  await browser.close(); 
 +  return { nameseen, pagesVisited }; 
 +}
  
-  Verify the BibTeX entry exists in https://measuretheweb.org/literature/bibliography. If not, add it there+// Same-origin links on the current page, in DOM order — the order a crawler 
-  - Use {[CitationKey]} where needed in the text; it will render as a numbered reference. +// gets them in unless it deliberately shuffles. 
-  - Keep this section unchanged to display the bibliography.+const links = (page) => 
 +  page.locator('a[href]').evaluateAll((as) => 
 +    as.map((a) => a.href).filter((h) => new URL(h).hostname === location.hostname));
  
-If any step fails, a purple warning will appear on the preview page. +const results = []; 
-*/+ 
 +results.push(await run('landing page only', async (page) => { 
 +  await page.goto(ORIGIN + '/'); 
 +  return 1; 
 +})); 
 + 
 +results.push(await run('landing + FIRST same-origin link (the HTTP Archive rule)', async (page) => { 
 +  await page.goto(ORIGIN + '/'); 
 +  const [first] = await links(page); 
 +  await page.goto(first); 
 +  return 2; 
 +})); 
 + 
 +results.push(await run('landing + ALL same-origin links from the landing page', async (page) => { 
 +  await page.goto(ORIGIN + '/'); 
 +  const ls = await links(page); 
 +  for (const l of ls) await page.goto(l); 
 +  return 1 + ls.length; 
 +})); 
 + 
 +results.push(await run('landing + all links, and scroll to the bottom of each', async (page) => { 
 +  await page.goto(ORIGIN + '/'); 
 +  const ls = await links(page); 
 +  for (const l of ls) { 
 +    await page.goto(l); 
 +    await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight)); 
 +    await page.waitForTimeout(200); 
 +  } 
 +  return 1 + ls.length; 
 +})); 
 + 
 +results.push(await run('landing + all links, scroll, and click every button', async (page) => { 
 +  await page.goto(ORIGIN + '/'); 
 +  const ls = await links(page); 
 +  for (const l of ls) { 
 +    await page.goto(l); 
 +    await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight)); 
 +    for (const b of await page.locator('button').all()) await b.click().catch(() => {}); 
 +    await page.waitForTimeout(200); 
 +  } 
 +  return 1 + ls.length; 
 +})); 
 + 
 +results.push(await run('depth 2: landing, its links, and their links, with scroll and click', async (page) => { 
 +  const visited = new Set(); 
 +  const queue = [ORIGIN + '/']; 
 +  let depth = 0; 
 +  while (queue.length && depth <= 2) { 
 +    const next = []; 
 +    for (const url of queue) { 
 +      if (visited.has(url)) continue; 
 +      visited.add(url); 
 +      await page.goto(url); 
 +      await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight)); 
 +      for (const b of await page.locator('button').all()) await b.click().catch(() => {}); 
 +      await page.waitForTimeout(200); 
 +      next.push(...(await links(page))); 
 +    } 
 +    queue.length = 0; 
 +    queue.push(...next.filter((u) => !visited.has(u))); 
 +    depth++; 
 +  } 
 +  return visited.size; 
 +})); 
 + 
 +site.close(); 
 + 
 +const W = Math.max(...results.map((r) => r.name.length)); 
 +console.log( 
 +  ['strategy'.padEnd(W), 'pages', ...BEACONS.map((b) => b.padStart(9))].join('  ') 
 +); 
 +console.log(['-'.repeat(W), '-----', ...BEACONS.map(() => '-'.repeat(9))].join('  ')); 
 +for (const r of results) { 
 +  console.log( 
 +    [ 
 +      r.name.padEnd(W), 
 +      String(r.pagesVisited).padStart(5), 
 +      ...BEACONS.map((b) => (r.seen.has(b) ? '✓' : '✗').padStart(9)), 
 +    ].join('  ') 
 +  ); 
 +
 +const pwVersion = (await import('playwright/package.json', { with: { type: 'json' } })).default.version; 
 +console.log(` 
 +t-landing  on the landing page 
 +t-article  on one subpage, at load 
 +t-scroll   on that subpage, only after scrolling to the bottom 
 +t-click    on another subpage, only after a button click 
 +t-deep     on a page linked only from a subpage, never from the landing page 
 + 
 +Playwright ${pwVersion}, Chromium ${chromiumVersion}, ${process.platform}. Needs no network.`); 
 +</file> 
 + 
 +===== Forms, Logins and the Half of the Web You Are Not Measuring ===== 
 + 
 +Of the 857 web crawls in this corpus, **553 (64.5%)** are recorded as not authenticating, **204 (23.8%)** do not say, and **at most 81 (9.5%)** got past a login of any kind — 42 by registering an account, 24 by logging in manually and 15 with automated login. Not one of the 857 used SSO.((The corpus has exactly one paper with ''authentication: sso'' — an Android subscription-app study — and it is not a web crawl, so it is outside this page's population.)) Whatever your topic, **at most one crawl in ten gets past a login**, and the reason is usually the one Lauinger et al. give: login walls stop deeper traversal. Treat the 553 with care: ''authentication'' shares the same single ''crawlConfig'' quote as the depth, and no discriminant was run for it, so an unknown share of those ''none'' values are the extractor's default reading of a paper that simply never mentions logging in. 
 + 
 +Two things worth knowing before you decide the effort is not worth it. 
 + 
 +**Interacting with forms buys real coverage, and it is measurable.** EvoCrawl replaces "fill every field and trigger every event" with an evolutionary search over //sequences// of interactions, so that constraints between fields and between pages can be satisfied. Against three state-of-the-art scanners on ten web applications, it reports "a 59% increase in code coverage and successfully submits HTML forms 5× more frequently than the next best tool" {[guo2025_evocrawl]}. The mechanism generalises beyond vulnerability scanning: a lot of a site's third-party behaviour lives behind a state you have to //create//, not merely a page you have to //reach//
 + 
 +**Typing is not the same as setting ''value''.** Senol et al., measuring exfiltration of email and password fields before submission, describe the countermeasure explicitly {[senol2022_leaky]}: 
 + 
 +> we simulate user typing behavior by using randomized intervals for each key press and dwell times, as well as the delay times between each press 
 + 
 +A form-filler that assigns to ''input.value'' fires no ''keydown'', no ''keyup'' and no ''input'' event unless the framework listens for programmatic changes, so the very scripts you are trying to catch never run. If your measurement is about what happens //while// a user types, you must actually type. Playwright's ''locator.pressSequentially()'' and Puppeteer's ''ElementHandle.type()'' with a ''delay'' both do this; ''locator.fill()'' does not. 
 + 
 +The rest of the login problem — Shepherd-style automated login, SSO, and automated registration — is [[Programming:Registration|Automating Login and Registration to Websites]], **currently a stub**, so expect to go to the papers directly for now. 
 + 
 +===== Your Crawler Will Be Noticed ===== 
 + 
 +Interaction is the axis on which a crawler most visibly stops resembling a user, and the share of papers that say so is rising: **not one of the 80 web crawls in the 2010–2013 bucket describes bot or crawler detection in a first-person sentence — three mention it in passing — against 11.8% of the 2025–2026 bucket.** 
 + 
 +The concrete failure modes to plan for: 
 + 
 +  * **A challenge you cannot pass.** Drakonakis et al., auditing authentication flows: "In 22 cases, there was some form of an anti-bot challenge that our system was not able to solve and, thus, could not proceed with registration." {[drakonakis2020_cookie]} That is a **non-random** loss: the sites with the most aggressive anti-bot posture are not a random sample of sites. 
 +  * **Different content, not an error.** Cloaking is served, not refused. Whether you were cloaked is not visible in your success rate. 
 +  * **Interaction is itself the tell.** A crawler that never scrolls, never moves the mouse and clicks in the geometric centre of every element is easy to classify. Adding interaction to look more like a user and adding interaction to measure more of the page are the same action with two justifications, and papers often only give the second. 
 + 
 +The gap between crawler and user is large and one-directional. Zeber et al. compared an OpenWPM crawl against telemetry from over 50,000 opt-in Firefox users over the same period: a median of **11.6** third-party domains per crawler visit against **4.5** for humans, and **6.1** tracking domains against **1.9**, on the same site domains {[zeber2020representativeness]}. Statefulness, vantage point, automation and interaction all differ at once there, so it is not a clean experiment on this axis — but it is the size of the target you are trying to hit. 
 + 
 +===== Which Methods Are Current ===== 
 + 
 +Dating methods matters more here than on most pages, because the corpus's own centre of mass is 2018–2024 and a purely corpus-driven reading would present the mid-window default as best practice. 
 + 
 +^ Method ^ Status ^ Evidence ^ 
 +| **Landing-page-only crawls of a ranked list** | **Still the single commonest design, and still defensible for the right question** — but no longer defensible //silently//. Since 2020 there is a citable reason to justify it or drop it | 155 of 417 depth-stating web crawls; {[aqeel2020_landing]}, {[urban2020beyond]} | 
 +| **"Plus a handful of random subpages"** | **Current practice**, and not derived from any measurement. The overall median is 10; per four-year bucket it is 5, 5, 10, 15 and 5, on 8, 11, 37, 33 and 15 papers — too few to call a trend either way | 104 papers give a count | 
 +| **A saturation study to choose the count** | **Done once, in 2020, and not replicated.** If you do it for your own metric you will be the second | {[urban2020beyond]} | 
 +| **A purpose-built internal-page top list** | **Superseded by circumstance.** Hispar is offline and its bootstrap list is retired. The HTTP Archive's one-secondary-page-per-site is what remains, with a known selection rule | {[aqeel2020_landing]}; checks of 2026-08-27 | 
 +| **Scrolling as a routine step** | **Rising and not yet standard** — 2.5% of 2010–2013 web crawls11.1% of 2025–2026 | full-text sweep | 
 +| **Mouse-movement and hover emulation** | **Never established.** Around 2% throughout, with no trend. Do not assume reviewer expects it, and do not claim realism from it | full-text sweep | 
 +| **LLM-agent-driven browsing** | **Genuinely new, and thin.** First appears in **2025**; **5 of 857** web crawls in the whole corpus use an agent as the browsing instrument, all in 2025–2026 | see below | 
 + 
 +==== The LLM-agent slice, counted honestly ==== 
 + 
 +A full-text sweep for agent frameworks and LLM-driven browsing over the 857 web crawls returns **35** papers. Reading each one's deciding sentence puts them in six groups: 14 use an LLM for text classification with no browsing at all, 9 study agents as the //subject// of measurement, 5 are reference-list citations, 2 use a vision-language agent to solve CAPTCHAs, and **5 use an agent as the instrument that does the browsing** — YuraScanner {[stafeev2025_yurascanner]}, an LLM-driven dark-pattern auditor across 456 data-broker sites {[sun2026_suitability]}, a multi-agent persona-driven traffic generator for website fingerprinting {[song2026_wfpllm]}, a passkey-adoption crawl built on Playwright plus the Browser Use framework {[jannett2026_passkeys]}, and one mobile-app equivalent. 
 + 
 +That is **0.6% of web crawls**, and every one is from 2025 or 2026. So: 
 + 
 +  * **It is real.** Song et al. is the sharpest case for it: models trained on scripted-crawler traffic scored under 10% accuracy against traffic from 30 real users, and training on LLM-agent, persona-driven browsing instead put accuracy "into the 80% range" {[song2026_wfpllm]}. If your measurement is downstream of anything learned from crawler traffic, scripted-crawl realism is the dominant error term, not a caveat. 
 +  * **It is not yet a method with known properties.** Sun et al. report verified workflow completion of **87%** and **79%** in two phases across 456 data-broker sites {[sun2026_suitability]} — that is a paper about whether the technique works, which is the stage the technique is at. 
 +  * **The evidence base is the thinnest part of this corpus.** 2026 venue-years are incomplete by construction. Five papers is a signal, not a rate; treat "LLM agents are now how this is done" as unsupported. 
 + 
 +===== What to Report ===== 
 + 
 +A methods paragraph that answers these is enough for a reviewer to know what your numbers count. None of them takes more than a clause. 
 + 
 +  - **The unit.** Pages or sites? If a site contributed several pages, is your prevalence over sites or over pages? Say which, and say how you aggregated (any-page, majority, mean). 
 +  - **The depth.** Landing page only, landing plus //N//, or traverse to depth //d// with budget //b//. If you stayed on the landing page, say so — it is a legitimate choice with a citable justification. 
 +  - **How you chose the pages.** The link-selection rule verbatim: same-origin or same-site, DOM order or random, seed if random, exclusions, and whether the frontier was harvested once and frozen or re-harvested per arm. 
 +  - **What happened on the page.** Scroll? Click? Type? Wait how long, and for what event — ''load'', ''networkidle'', a fixed timer? A fixed timer is fine; an unstated one is not. 
 +  - **What you did about the banner and the login**, with a pointer to [[Privacy:Consent]] and [[Programming:Registration]]. 
 +  - **The failures.** How many target sites yielded zero pages, how many yielded fewer subpages than you asked for, and how many hit a challenge you could not pass. All three are non-random. 
 +  - **The comparison, if you make one.** If you compare against a published prevalence, check the other paper's depth first. A 3× difference in request counts is available from the depth choice alone {[iqbal2022_khaleesi]}. 
 + 
 +===== What a Complete Statement Looks Like ===== 
 + 
 +Two sentences from Aziz and Wilson are, as far as this corpus goes, the model {[aziz2024_johnny]}: 
 + 
 +> For each domain, we programmed the crawler to load the domain's homepage, scroll to the bottom of the page, then sleep for 25 seconds. Further, we programmed our crawler to select nine internal hyperlinks at random from the homepage and crawl them using the same load, scroll, and sleep approach. 
 + 
 +Five of the seven items on the checklist above are in those two sentences: the unit (domain), the depth (homepage plus nine), the selection rule (at random, from the homepage), the on-page action (scroll to the bottom) and the wait (25 seconds, stated). Plus the detail that most often silently differs and is on none of the checklists: the subpages get the **same** load-scroll-sleep treatment as the landing page, which is what makes a landing-versus-subpage comparison a comparison rather than two different instruments. The two items it does not cover are the consent treatment — which is elsewhere in that paper, whose whole design is four experimental conditions — and the failure counts. Splitting them across the methods section is the usual and fine arrangement; leaving them out is not. 
 + 
 +Five of seven, in two sentences. That is the whole cost. 
 + 
 +===== If You Just Need a Default ===== 
 + 
 +Absent a better reason — and the sections above are the better reasons — this is a defensible starting design for a privacy or security crawl over a ranked site list, and every element of it is something you can point a reviewer at: 
 + 
 +  - **Harvest the frontier once.** Visit each landing page, collect its same-site links, store them with the date. Freeze that list and replay it in every arm of the experiment. 
 +  - **Pick subpages at random from it, with a published seed**, and publish the exclusion list if you use one. Do not take them in DOM order unless you want the navigation chrome. 
 +  - **Start at ten and run a saturation pilot for //your// metric** on a few hundred sites before committing to the number. Ten is the field's median and 100 is where the one published curve flattens; you will not know which is right for a metric nobody has plotted. 
 +  - **On every page, including the landing page: scroll to the bottom, then wait a fixed, stated time.** Same treatment on the subpages as on the landing page, or the comparison between them is not a comparison
 +  **Click nothing by default.** Add clicking only where your question needs it, and when you do, exclude ad elements — see [[#Interacting is not free, and it is not only your cost|above]]. 
 +  - **Crawl logged out**, and say so. Getting past a login is a project, not a setting. 
 +  - **Log the failures** — sites yielding zero pages, sites yielding fewer subpages than asked, challenges you could not pass — and report all three. 
 + 
 +The point of the default is not that it is optimal. It is that every line of it is a sentence you can write in the methods section, which is more than most published crawls manage. 
 + 
 +===== Methodology and Limitations of These Figures ===== 
 + 
 +All corpus figures on this page come from the extraction over the seven venues in [[literature:corpus|the publication corpus]] — CCS, IMC, NDSS, PETS, USENIX Security, TheWebConf and IEEE S&P, 2010–2026. EuroS&P, ACSAC, RAID, AsiaCCS, CHI and SOUPS are not in it, so every claim here is a claim about those seven venues. 
 + 
 +Three limitations specific to this page: 
 + 
 +  * **The denominator is 857, not 5,859.** Only 1,120 papers in the corpus ran a crawl at all, and 857 of those crawled the web. The depth ratios use a further-narrowed denominator of 417 for the reason given [[#Depth has more than three positions|above]]. 
 +  * **''crawlConfig'' carries one evidence quote for the whole object** — shared by the browser, the statefulness, the consent action, the depth and four other keys. Measured on a reproducible sample of 12 papers that state both a depth and a subpage count: **6 of the 12 shared quotes evidence the depth, 5 evidence a different key entirely** (statefulness, vantage, repeat visits) and 1 is about visit structure rather than site depth. So the site's usual "read the evidence quote" check cannot validate a depth label about half the time. In place of it, the provenance page reports a **discriminant**: whether each paper's own text contains a first-person sentence naming the site root, or something below it, or both, or neither. The labels do track the text — ''landing-page-only'' papers name a deeper unit and nothing else in **4 of 155** cases, while the ''not-stated'' control has neither phrase in **83.8%** of cases — but **42 of 155 (27.1%)** ''landing-page-only'' papers contain neither phrase, and a hand-read sample of those found the label is a defensible inference from "we visited each website" rather than a stated depth. The 81.9% "states a depth" figure should therefore be read as an upper bound. 
 +  * **The on-page-action figures are upper bounds by construction.** They count papers whose text matches a pattern in a first-person sentence, not papers that did the thing. 
 + 
 +The full query log, the report script and its unedited output, the folds and their residue, the quotes spot-checked, the external sources verified and rejected, and what could not be established are on **[[provenance:programming:interaction]]**. 
 + 
 +===== Open Questions ===== 
 + 
 +<WRAP todo> 
 +//"Nobody" below means "no paper in this corpus's seven venues, 2010–2026". EuroS&P, ACSAC, RAID, AsiaCCS, CHI and SOUPS are not in it, and neither is the web-performance literature outside IMC.// 
 + 
 +  * **Nobody has repeated the saturation study.** Urban et al.'s curve is one metric (cookies), one rank band (top 1,000), one year (2019–2020). A 2026 replication for distinct third-party domains, for ad slots, and for the long tail of the ranking would settle the number the whole field is guessing at. 
 +  * **Selection rule versus count, held apart.** No paper in this corpus varies //which// subpages it picks while holding //how many// fixed. Ten nav links, ten random links and ten search-popular pages from the same sites would answer whether the rule or the count dominates. 
 +  * **What does a scroll actually add, at scale?** The fixture on this page shows it can matter. Nobody has published the distribution of "third parties visible only after scrolling" over a real site list. 
 +  * **A replacement for Hispar.** The HTTP Archive's one-first-link-per-site is a start and is not a sample. A maintained, versioned, reproducible internal-page list is a genuine gap and a small enough artefact for one group to own. 
 +  * **How much does an LLM agent actually change the measurement, and at what cost per site?** The five papers using one report task success, not measurement deltas. The comparison that matters — same site list, scripted crawl versus agent crawl, same metric — has not been published. 
 +</WRAP> 
 + 
 +===== Related Pages ===== 
 + 
 +  * [[Privacy:Consent|Granting Consent to Websites]] — the interaction with the highest stakes, and the one with its own literature. 
 +  * [[Programming:Stateful Stateless|Stateful and Stateless Crawling]] — whether the interaction you performed is still in effect on the next page. 
 +  * [[Programming:Registration|Automating Login and Registration to Websites]] — the logged-in web this page's 9.5% figure is about. 
 +  * [[Programming:Crawler|Comparison of Crawling Libraries]] — which of these actions each library can actually perform. 
 +  * [[Design:Website selection]] and [[Design:Sampling|Representative Sampling Methods]] — the site list, and why subpage selection is a sampling problem with the same failure modes. 
 +  * [[Privacy:Requests|Classifying Web Requests]] — what to do with the 3× more requests an interactive crawl produces. 
 +  * [[Design:Automated measurements]] — the containing design decision. 
 + 
 +====== References ======
  
 <bibtex bibliography></bibtex> <bibtex bibliography></bibtex>
Line 73: Line 617:
 /* This enables discussion under this article. */ /* This enables discussion under this article. */
 ~~DISCUSSION~~ ~~DISCUSSION~~
 +
programming/interaction.1742374311.txt.gz · Last modified: by karelkubicek

Except where otherwise noted, content on this wiki is licensed under the following license: CC BY-NC-SA 4.0
CC BY-NC-SA 4.0 Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki