An introduction to website types and their differences
Back in the day, when I was a child, during my childhood, all websites were static. That is, they consisted only of HTML, CSS, and a few snippets of JavaScript. Back then, if you got a page, you knew that was all the site had to offer (in terms of content).
Scraping such sites is a breeze; you just need to know what you need to scrape and where it is. Now, however, most websites on the web are dynamic.
What does a dynamic website mean? It means that the page you see in your browser isn't stored separately somewhere on the server, but is assembled on the fly and served when ready. This means a website doesn't have to use JavaScript to be dynamic; the fact that the page is assembled is enough.
Parsing such websites is significantly more difficult because they require:
- Either precise timing - the page can't be downloaded immediately, only after the required content appears on the page.
- Or JavaScript rendering - sometimes direct interaction with the site via clicking, scrolling, or focusing on an element is required for the required content to load, and this content is loaded via JavaScript.
Preparation: what, who, and how we'll scrape
As an example of parsing, I'll use my own website. We'll scrape article cards (Title, Link, and Description).

My website uses a paginator and dynamic loading upon reaching a certain height. Also, although not always, websites can update the current URL when loading new content, like mine does. For example, changing the current page number or adding a filter.
There are four methods for parsing, or rather, obtaining the necessary data from this type of website:
1. Browser emulation and rendering of JS scripts
- Direct browser emulation via drivers - Selenium
- Browser emulation via special software APIs - Playwright / Puppeteer / Cypress
2. Reverse engineering the website and its requests
- Using an open, specially developed API for third-party parsers
- Finding and using a hidden API not provided by the developer
4. Gaining direct access to databases and the website (i.e., hacking the target)
I will only discuss the first three, as the fourth is illegal. Please don't hack other people's websites. This way, we'll write scrapers that will do almost the same thing, but in different ways and using different technology stacks. I'll also discuss the advantages and disadvantages of each of these methods.
We'll start with the first point and the first subpoint—using Selenium.
Scraping a dynamic websites in different ways
Website scraping using Selenium
The main advantage of parsing websites with Selenium is that it supports a huge number of browsers, including Chrome, Edge, Firefox, Safari, and Internet Explorer. And an equally large number of programming languages: Python, Kotlin, JS, Java, C#, and Ruby.
However, it has one significant drawback: it's very slow due to the fact that all interaction occurs through special drivers that emulate browser behavior.
I'll be writing this parser in Python, and the rest of the environment will be built around this language. Create a directory and virtual environment for the project, and install the necessary packages:
Once the project directory has been created and everything is configured, let's add the main script file. In it, we'll launch the web driver, make the first request to the first page, and save it.
So far, there haven't been any changes. We could get the exact same page without Selenium. After all, we still have 15 pages that we can't access except through Selenium.
To parse all available pages, we'll either need to click all 15 buttons or scroll down to the bottom. First, let's see what it looks like if we parse by clicking buttons:
Initially, we might not know how many pages are available, so after we visit the site, we look at the number of available pages on the paginator.
Then we create a loop and click the "Next" button to get to the next page.
But how do we know if the page has loaded or is still loading? There are many options if you're using Selenium. You can either specify how many seconds you're willing to wait, or wait for the appearance, absence, or visibility of a specific element on the page, using a special construct with WebDriverWait.
Without the --headless flag, it would look something like this:
Scraping a website using Playwright
Although Playwright supports Python, I still prefer to work with it as an npm project. Unlike Selenium, it's much faster. However, it doesn't support all browsers, only Chromium (Google Chrome, Edge), WebKit (Safari), Gecko (Firefox), and their derivatives.
So, after installing Playwright, to scrape all available articles from the pagination page, you can write the following script:
This scraper clicks the "Next" button and only at the end scrape the entire loaded page. This could be done in a loop if this site's paginator simply replaced one article with another. But since it simply appends new articles to existing ones, it will work like this.
When scraping dynamic sites, the most important rule is to understand this. Everything takes time, especially when it comes to the user interface, so waiting and handling events when certain elements are ready is everything.
Website scraping using an existing API
This is probably the most reliable and fastest way to collect data from a target website. Although it's quite rare, it's usually done only by large sites like Google or very small sites run by enthusiasts and geeks like me. :)
The existence of such an API is usually mentioned directly. After all, it should reduce the server load. What's simpler? Requesting 1,000 entire HTML pages of a website, or 100 lightweight JSON files that already contain all the existing information—just copy and paste.
My website also has an open API located at this address: https://timthewebmaster.com/api/v1/public/
So, after playing around a bit, you can figure out that to get all the articles you need, you can create a GET request to https://timthewebmaster.com/api/v1/public/article/?page=1&page_size=100&format=json and retrieve all the articles at once. In a script, it would look like this:
Then, all that's left to do is iterate through the resulting list and select only the data you need. Having such an API greatly simplifies the work, essentially reducing it to sorting and packaging the data into more convenient and relevant formats for the client.
But again, this option is very rare. It either won't exist at all, or the API won't be explicit. The next chapter will cover how to find such an API.
Site Parsing Using a Hidden API
The script will be identical to the previous one. The only difference is finding such an API. To find such an API, you can use the developer console. In the console, go to the Network tab and select XHR and JS. Next, interact with the page (click a button, hover over it, scroll down) and monitor the intercepted requests.
The server can return these POST requests, or rather responses to them, in various formats. They can range from a simple piece of HTML code to a full-fledged JSON file. It all depends on the specific site. In my case, a rendered HTML fragment is returned, which then needs to be parsed using BeautifulSoup or other parsers.
Site scraing via a browser extension
This method is ideal if you need to parse data from websites under any, even the most sophisticated, protection quickly and immediately, but a real user will have to access such sites. Take, for example, my recent browser extension for scraping the Avito marketplace; it is considered like a very tough website to scrape anything. But with an extension, you can get a pretty useful personal scraper.
Yes, you can get creative and install such extensions on Selenium or Playwright, but it won't be much use. It won't help much in bypassing bot protection mechanisms. The only advantage of using extensions this way might be what I call "toolset swapping." That is, you can easily break through security using, for example, Python/Selenium, but parse and collect data using JS.
Conclusion
That's how you can scrape dynamic websites. There are two ways: either mimic browser behavior and render JS, or look for hidden (or not so hidden) APIs of these websites. Of course, parsing through these APIs is faster, cheaper, and easier, but sometimes website creators going insane and do everything possible to prevent their resource from being parsed.
It's understandable; it's unclear who makes hundreds and hundreds of requests to a web resource and why, thereby overloading it.
Therefore, before you start scrape a website, make sure you won't be hitting their servers too hard or too noticeably. Collect only the essentials. And if you need some practice, you're welcome to scrape my website :) Have a nice day.