Next-Gen App & Browser Testing Cloud
Trusted by 2 Mn+ QAs & Devs to accelerate their release cycles

Build a news scraper that handles infinite scroll, respects paywalls, strips boilerplate, dedupes syndication, and stays fresh using real cloud browsers.

Jaydeep Karale
Author

Saurabh Prakash
Reviewer
Last Updated on: July 6, 2026
You point a scraper at a newsroom homepage on Monday. It pulls fifteen clean headlines. By Friday the same job returns three, half of them cut off mid-sentence, and one row is a cookie banner. Nobody changed your code. The feed switched to infinite scroll, a wire story now appears under four different bylines, and the article you wanted sits behind a subscribe button.
News is one of the hardest verticals to scrape well because five problems land at once: feeds that never paginate, paywalls that draw a legal line, boilerplate that swamps the article body, syndication that clones the same story, and freshness windows measured in minutes. Most guides cover generic scraping and skip all five.
This engineering guide takes each problem in turn and answers it with a concrete technique, plus a real run on TestMu AI Browser Cloud that renders a JavaScript-heavy listing and extracts clean rows a plain request never sees. It builds on our Playwright for web scraping guide, which is the hub for browser-driven extraction.
Overview
What does scraping news at scale actually involve?
It means collecting article data (headline, byline, date, body) from many publishers on a schedule, then cleaning and de-duplicating what you pull. Five problems stack up at once, and a generic scraper handles none of them:
What do you need, and where is the line?
You need a real browser that renders JavaScript feeds, readability-style boilerplate removal, and a fingerprint dedup step. TestMu AI Browser Cloud runs those real Chrome sessions in parallel. The one hard boundary is the paywall: content you have not licensed stays off the table, so license a feed instead of stepping over the wall.
A product-catalog scrape reads a stable list of items with prices. News reads a moving stream where the same story is republished, the layout is buried under ads, and the most valuable content is often gated. The difficulty is not one hard thing; it is five medium things stacked together.
The distribution shape amplifies the syndication problem. A single wire report from a news agency is licensed to hundreds of outlets and republished, often verbatim, so a broad scrape meets the same story through many mirrored copies rather than one canonical source. That is why the dedup step covered later is not optional once you collect from more than a handful of publishers.
News feeds come in three pagination shapes, and each has a cleaner path than brute-forcing the DOM. Identify which one you are dealing with before writing extraction code.
The reason a browser is unavoidable for the last two is rendering. The median mobile page shipped 558 kilobytes of JavaScript in 2024, and on modern publishers that script is what assembles both the feed items and the article text after the initial load.
One shortcut worth checking first: an infinite-scroll feed almost always talks to a JSON or feed endpoint behind the scenes. Open the network tab, find the request that returns the next batch, and call it directly with the page or cursor parameter it uses. When that endpoint exists, it is faster and less brittle than scrolling the page. When it does not, drive the scroll in a real browser:
// Scroll an infinite feed until it stops growing (Playwright-style)
async function collectFeed(page, { maxRounds = 40, pause = 1200 } = {}) {
const seen = new Set();
let stable = 0;
for (let round = 0; round < maxRounds; round++) {
const links = await page.$$eval("a[href*='/article/'], a[href*='/news/']",
as => as.map(a => a.href));
links.forEach(l => seen.add(l));
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
await page.waitForTimeout(pause); // let the next batch render
const height = await page.evaluate(() => document.body.scrollHeight);
stable = height === page._lastHeight ? stable + 1 : 0;
page._lastHeight = height;
if (stable >= 3) break; // feed stopped growing
}
return [...seen];
}Always set a stop condition. A feed that keeps loading yesterday, last week, and last year will scroll forever, so cap the rounds, stop when the height stabilizes, or stop when you reach articles older than your freshness window. The same rendering challenge shows up in our guide to scraping dynamic web pages.
Note: Infinite-scroll feeds only load in a real browser. TestMu AI Browser Cloud gives you on-demand Chrome sessions that render JavaScript and run in parallel, so you scroll and extract without operating a headless fleet. Start free
A paywall is not a technical obstacle to route around. It is an explicit statement that the content is licensed, not free, and stepping over it can breach the publisher's terms of service and copyright. The honest position is simple: content behind a paywall you have not paid for is off the table.
That still leaves a large, legitimate surface, because most news is free to read. The Reuters Institute Digital News Report 2024 found that the proportion who pay for online news across 20 countries is just 17%, a figure flat for three years. The other side of that number is that the vast majority of published articles are readable without a subscription.
Draw the line clearly before you write extraction code. What follows is engineering guidance, not legal advice; for your specific use case, consult counsel.
A well-behaved scraper also rate-limits itself, identifies with an honest user agent, and avoids collecting personal data. Best-effort tooling such as stealth mode reduces friction on sites that block ordinary automation, but it is never a license to cross an access boundary a publisher has set.
On a news page, the article you want is a minority of the DOM. Around it sit the masthead, a mega-menu, a related-stories rail, a newsletter prompt, social buttons, a comment widget, and several ad slots. Boilerplate removal is the step that keeps the body and discards the rest.
Two approaches exist, and the second is far more durable across a fleet of publishers.
| Approach | How it works | Survives redesigns? | Scales to many sites? |
|---|---|---|---|
| Fixed CSS selectors | You hand-write a selector per site for the body container. | No, one layout change breaks it. | No, one selector set per publisher. |
| Readability-style extraction | Score each DOM block by text density and link ratio, keep the main content. | Mostly, it adapts to structure. | Yes, one algorithm across sites. |
A readability-style extractor walks the DOM, scores nodes by the ratio of text to links and markup, and keeps the highest-scoring contiguous block as the article. That is why it generalizes: it looks for the shape of an article rather than a named class that a redesign can rename overnight.
The critical detail is when you run it. Run boilerplate removal on the fully rendered page, not the raw HTML shell, because much of both the content and the clutter is injected by JavaScript after load. TestMu AI Browser Cloud can return page content in a readability format directly, which does the density scoring on the rendered DOM for you:
import { Browser } from '@testmuai/browser-cloud';
const client = new Browser();
// 'readability' strips nav, ads, and rails from the rendered DOM,
// returning the main article content instead of the raw shell.
const article = await client.scrape({
url: 'https://example-news-site.com/world/some-report',
format: 'readability',
lambdatestOptions: {
'LT:Options': { username: 'keys', accessKey: '<your-access-key>' }
}
});
console.log(article); // headline + clean body, boilerplate removedFor the fields around the body, lean on structured metadata the publisher already exposes. Most news pages embed NewsArticle or Article JSON-LD and Open Graph tags with the headline, author, and publish date, which is cleaner to read than parsing visible text and consistent across sites.
A news story is worth most in its first hour, and worth less every hour after. The scheduling goal is to notice new URLs quickly while spending almost no work re-checking articles you already have.
The pattern is an incremental crawl driven by a seen-set, not a full re-scrape on every run.
Where you want a scheduled check to also validate that a rendered page still looks right, a deterministic browser agent fits the job. TestMu AI Kane CLI is a browser agent for developers, AI agents, and CI/CD that drives a real Chrome session from natural-language objectives, so a scheduled pipeline can confirm a feed rendered and the expected article shell loaded before the extractor runs, then export the steps as reusable code.
To ground the pattern, here is an actual run of the TestMu AI Browser Cloud SDK against a rendered, JavaScript-heavy listing, standing in for a news section front. It renders the page in a real Chrome session and parses listing rows out of the hydrated DOM, the same shape as pulling headlines from a feed.
import { Browser } from '@testmuai/browser-cloud';
const client = new Browser();
const data = await client.scrape({
url: 'https://ecommerce-playground.lambdatest.io/',
format: 'text',
lambdatestOptions: {
'LT:Options': { username: 'keys', accessKey: '<your-access-key>' }
}
});
const text = typeof data === 'string' ? data : (data.text || JSON.stringify(data));
const lines = text.split('\n').map(l => l.trim()).filter(Boolean);
// Parse "listing rows" out of the rendered DOM, the way you would
// pull headlines from a news feed.
const rows = lines.filter(l => /^(HTC|iMac|MacBook|iPhone|Samsung|Canon)/i.test(l));
rows.slice(0, 6).forEach((r, i) => console.log(` ${i + 1}. ${r}`));The real console output from that run:
[browser-cloud] starting real session against LambdaTest Ecommerce Playground
[browser-cloud] rendered page in 8.4s, extracted 2939 chars of text
[browser-cloud] sample product listings parsed from rendered DOM:
1. iMac
2. iMac
3. iMac
4. iMac
5. HTC Touch HD
6. HTC Touch HD
[browser-cloud] total candidate listing rows found: 6
[browser-cloud] doneTwo things in that output map straight to news extraction. First, the content only exists because a real browser executed the page's JavaScript; a raw request would have returned an empty shell. Second, look at the rows: iMac appears four times and HTC Touch HD twice, the exact duplication you get when a syndicated story is mirrored across a feed, which is why the fingerprint dedup step earlier is not optional.
Every session also records video, console, and network logs, so when an extraction returns empty rows you can watch what the page actually rendered instead of guessing. For code examples in your own tests, the Selenium Playground gives you stable, public pages to point a scraper at.
Start with one publisher and one section, and get the full path working before you fan out: discover new URLs from a feed, render each in a real browser, strip boilerplate to the body, fingerprint for dedup, and store with provenance. Only then add more sites, because each new publisher tests your boilerplate and dedup logic, not your plumbing.
Put the rendering on managed infrastructure so scale and debuggability are not your problem. TestMu AI Browser Cloud provisions real Chrome sessions on demand, runs them in parallel, and captures per-session video and logs, and its readability format returns clean article content from the rendered DOM. Wire the SDK following the Browser Cloud documentation, and pair it with a browser-automation workflow like the ones in our browser automation guide.
Keep the guardrails permanent, not an afterthought: read each site's robots.txt and terms, stay off paywalled content you have not licensed, rate-limit and back off on errors, and store the source URL and publish time with every record so provenance survives dedup. A news scraper that is fast, clean, and well-behaved beats one that is merely fast.
Author
Reviewer
Saurabh Prakash is an Engineering Manager at TestMu AI (formerly LambdaTest), where he leads engineering on agentic AI development and scalable system architecture for the quality engineering platform. He has also contributed to Test at Scale, the company's open-source test intelligence platform. He brings over 9 years of experience across Node.js, Java, Spring, MVC, data structures, algorithms, and scalable system design, with earlier roles as SDE 2 at Zomato, Senior Software Engineer at LogicHub, and Software Development Engineer at Directi. Saurabh holds a B.Tech in Computer Science and Engineering from Delhi Technological University.
Did you find this page helpful?
More Related Blogs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance