<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dávid Lukáč</title>
    <description>The latest articles on DEV Community by Dávid Lukáč (@davidlukacapify).</description>
    <link>https://dev.to/davidlukacapify</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F972899%2F9a4c69a7-691f-471a-8b5d-87b991d6f4ea.jpeg</url>
      <title>DEV Community: Dávid Lukáč</title>
      <link>https://dev.to/davidlukacapify</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidlukacapify"/>
    <language>en</language>
    <item>
      <title>10 web scraping challenges (+ solutions) in 2025</title>
      <dc:creator>Dávid Lukáč</dc:creator>
      <pubDate>Thu, 05 Dec 2024 15:04:45 +0000</pubDate>
      <link>https://dev.to/apify/10-web-scraping-challenges-solutions-in-2025-5bhd</link>
      <guid>https://dev.to/apify/10-web-scraping-challenges-solutions-in-2025-5bhd</guid>
      <description>&lt;p&gt;Web scraping comes with its fair share of challenges. Websites are becoming increasingly difficult to scrape due to the rise of anti-scraping measures like CAPTCHAs and browser fingerprinting. At the same time, the demand for data, especially to fuel AI, is higher than ever. &lt;/p&gt;

&lt;p&gt;As you probably know, web scraping isn’t always a stress-free process, but learning how to navigate these obstacles can be incredibly rewarding.&lt;/p&gt;

&lt;p&gt;In this guide, we’ll cover 10 common problems you’re likely to encounter when scraping the web and, just as importantly, how to solve them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.apify.com/web-scraping-challenges/#1-dynamic-content" rel="noopener noreferrer"&gt;Dynamic content
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://blog.apify.com/web-scraping-challenges/#2-user-agents-and-browser-fingerprinting" rel="noopener noreferrer"&gt;User agents and browser fingerprinting
&lt;/a&gt;
3.&lt;a href="https://blog.apify.com/web-scraping-challenges/#2-user-agents-and-browser-fingerprinting" rel="noopener noreferrer"&gt;Rate limiting&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.apify.com/web-scraping-challenges/#4-ip-bans" rel="noopener noreferrer"&gt;IP bans
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.apify.com/web-scraping-challenges/#5-honeypot-traps" rel="noopener noreferrer"&gt;Honeypot traps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.apify.com/web-scraping-challenges/#6-captchas" rel="noopener noreferrer"&gt;CAPTCHAs
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.apify.com/web-scraping-challenges/#7-data-storage-and-organization" rel="noopener noreferrer"&gt;Data storage and organization
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; &lt;a href="https://blog.apify.com/web-scraping-challenges/#8-automation-and-monitoring" rel="noopener noreferrer"&gt;Automation and monitoring
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.apify.com/web-scraping-challenges/#9-scalability-and-reliability" rel="noopener noreferrer"&gt;Scalability and reliability
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.apify.com/web-scraping-challenges/#10-real-time-data-scraping" rel="noopener noreferrer"&gt;Real-time data scraping&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the solutions, we’ll use Crawlee, an open-source library for Python and Node.js, and the Apify platform. These tools make life easier, but the techniques we’ll talk about can be used with other tools as well. By the end, you’ll have a solid understanding of how to overcome some of the toughest hurdles web scraping can throw at you. &lt;/p&gt;

&lt;h2&gt;
  
  
  1. Dynamic content
&lt;/h2&gt;

&lt;p&gt;Modern websites often use JavaScript frameworks like React, Angular, or Vue.js to create dynamic and interactive experiences. These &lt;a href="https://blog.apify.com/scraping-single-page-applications-with-playwright/" rel="noopener noreferrer"&gt;single-page applications (SPAs)&lt;/a&gt; load content on the fly without refreshing the page, which is great for users but can complicate web scraping.&lt;/p&gt;

&lt;p&gt;Traditional scrapers that pull raw HTML often miss data generated by JavaScript after the page loads. To &lt;a href="https://blog.apify.com/scrape-dynamic-websites-with-python/" rel="noopener noreferrer"&gt;capture dynamically loaded content&lt;/a&gt;, scrapers need to execute JavaScript and interact with the page, just like a browser.&lt;/p&gt;

&lt;p&gt;That’s where headless browsers like Playwright, Puppeteer, or Selenium come in. They mimic real browsers, loading JavaScript and revealing the data you need.&lt;/p&gt;

&lt;p&gt;In the example below, we’re using &lt;a href="https://github.com/apify/crawlee" rel="noopener noreferrer"&gt;Crawlee&lt;/a&gt;, an open-source web scraping library, with Playwright to scrape a dynamic page (MintMobile). While Playwright alone could handle this, Crawlee adds powerful web scraping features you’ll learn about in the next sections.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PlaywrightCrawler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Dataset&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crawlee&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;firefox&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;playwright&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crawler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PlaywrightCrawler&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;launchContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Here you can set options that are passed to the playwright .launch() function.&lt;/span&gt;
        &lt;span class="na"&gt;launchOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;headless&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;launcher&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;firefox&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;requestHandler&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;log&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Extract data&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#WebPage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1[data-qa="device-name"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a[data-qa="storage-selection"] p:nth-child(1)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
                &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;devicePrice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a[data-qa="storage-selection"] p:nth-child(2)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
                &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;productInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`No product info found on &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Extracted product info from &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// Save the extracted data, e.g., push to Apify dataset&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pushData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productInfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Start the crawler with a list of product review pages&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crawler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://www.mintmobile.com/devices/samsung-galaxy-z-flip6/6473480/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. User agents and browser fingerprinting
&lt;/h2&gt;

&lt;p&gt;If a website blocks your scraper, you can’t access the data, which makes all your efforts pointless. To avoid this, you want to make your scrapers mimic real users as much as possible. Two basic elements of anti-bot defenses to keep in mind are &lt;strong&gt;user agents&lt;/strong&gt; and &lt;strong&gt;browser fingerprinting.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A user agent is a piece of metadata sent with every HTTP request, telling the website what browser and device are making the request. It looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your scraper uses something obvious like the Axios default User Agent, &lt;code&gt;axios/1.7.2&lt;/code&gt; , the site will likely flag you as a bot and block your access.&lt;/p&gt;

&lt;p&gt;Fingerprinting takes it a step further. Websites analyze details like your screen resolution, installed fonts, timezone, language, and even whether the browser is running in headless mode. All this data creates a unique “fingerprint” for your scraper. If your fingerprint looks too uniform or lacks variety, like using the same resolution or timezone across all requests, you’re more likely to get caught. Some sites can even track you across sessions, bypassing tactics like IP rotation.&lt;/p&gt;

&lt;p&gt;As you can imagine, manually managing user agents and fingerprints can be a headache, it’s time-consuming, error-prone, and hard to keep up with as websites constantly improve their defenses.&lt;/p&gt;

&lt;p&gt;Thankfully, modern open-source tools like Crawlee take care of these challenges for us. Crawlee automatically applies the correct user agent and fingerprints to our request to ensure our bots appear “human-like.” Its &lt;code&gt;PlaywrightCrawler&lt;/code&gt; and &lt;code&gt;PuppeteerCrawler&lt;/code&gt; also make headless browsers behave like real ones, lowering your chances of detection, which is why I opted for using Playwright with Crawlee in the first section 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Rate limiting
&lt;/h2&gt;

&lt;p&gt;Rate limiting is how websites keep things under control by capping the number of requests a user or IP can make within a set time frame. This helps prevent server overload, defend against DoS attacks, and discourage automated scrapers. If your scraper goes over the limit, the server might respond with a &lt;strong&gt;429 Too Many Requests&lt;/strong&gt; error or even block your IP temporarily. This can be a major roadblock, interrupting your data collection and leaving you with incomplete results.&lt;/p&gt;

&lt;p&gt;To solve this issue, you need to manage your request rates and stay within the website’s limits. Crawlee makes this easy by offering options to fine-tune how many requests your scraper sends at once, how many it sends per minute, and how it scales based on your system’s resources. This gives you the flexibility to adjust your scraper to avoid hitting rate limits while maintaining strong performance.&lt;/p&gt;

&lt;p&gt;Here’s an example of how to handle rate limiting using Crawlee’s &lt;strong&gt;CheerioCrawler&lt;/strong&gt; with adaptive concurrency to scrape &lt;a href="https://news.ycombinator.com/" rel="noopener noreferrer"&gt;Hacker News:&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CheerioCrawler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Dataset&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crawlee&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crawler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CheerioCrawler&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// Ensure there will always be at least 2 concurrent requests&lt;/span&gt;
    &lt;span class="na"&gt;minConcurrency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// Prevent the crawler from exceeding 20 concurrent requests&lt;/span&gt;
    &lt;span class="na"&gt;maxConcurrency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// ...but also ensure the crawler never exceeds 250 requests per minute&lt;/span&gt;
    &lt;span class="na"&gt;maxRequestsPerMinute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;requestHandler&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;enqueueLinks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;log&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Processing &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;...`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Extract data using Cheerio&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.athing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;$element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.title a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                    &lt;span class="na"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.rank&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                    &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.title a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="p"&gt;};&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Store the results to the default dataset.&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pushData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Find a link to the next page and enqueue it if it exists.&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;infos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;enqueueLinks&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.morelink&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;infos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;processedRequests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is the last page!`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crawler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addRequests&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://news.ycombinator.com/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// Run the crawler and wait for it to finish.&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crawler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Crawler finished.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. IP bans
&lt;/h2&gt;

&lt;p&gt;Building on the discussion about rate limiting, IP bans are another common issue you might have come across when scraping the web. Simply put, when a scraper sends too many requests too quickly or behaves in ways that don’t seem natural, the server might block the IP address, either temporarily or permanently. When that happens, your data collection comes to a complete halt, and naturally, we want to prevent this from happening.&lt;/p&gt;

&lt;p&gt;While managing your scraper’s concurrency can help avoid this, sometimes it’s not enough. If you’re still running into blocks, using proxy rotation is a great next step. By rotating IP addresses, you can spread out your requests and make it harder for websites to flag and block your crawler’s activity.&lt;/p&gt;

&lt;p&gt;With Crawlee, adding proxies is straightforward. Whether you’re using your own servers or working with a third-party provider, Crawlee handles the rotation automatically, ensuring your requests come from different IPs.&lt;/p&gt;

&lt;p&gt;If you already have a list of proxies ready, integrating them into your Crawlee scraper takes just a few lines of code. Here’s how you can do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProxyConfiguration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CheerioCrawler&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crawlee&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proxyConfiguration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ProxyConfiguration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;proxyUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://proxy-1.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://proxy-2.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proxyUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;proxyConfiguration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newUrl&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crawler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CheerioCrawler&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;proxyConfiguration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// ...rest of the code&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you can use a third-party tool like &lt;a href="https://apify.com/proxy" rel="noopener noreferrer"&gt;Apify Proxy&lt;/a&gt; to access a large pool of residential and datacenter proxies, making proxy management even easier. It also gives you added flexibility by letting you control proxy groups and country codes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Actor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proxyConfiguration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Actor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createProxyConfiguration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RESIDENTIAL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;countryCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;US&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proxyUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;proxyConfiguration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newUrl&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Honeypot traps
&lt;/h2&gt;

&lt;p&gt;Honeypot traps are hidden elements in a website’s HTML designed to detect and block automated bots and scrapers. These traps, like hidden links, forms, or buttons, are invisible to regular users but can be accidentally triggered by scrapers that process every element indiscriminately. When this happens, it signals bot activity to the website, often resulting in blocks, IP bans, and other issues. In short, you want to keep your scraper far away from these traps.&lt;/p&gt;

&lt;p&gt;One way to avoid these traps is by filtering out hidden elements. You can check for CSS properties such as &lt;code&gt;display: none&lt;/code&gt; and &lt;code&gt;visibility: hidden&lt;/code&gt; to exclude them from your scraping process.&lt;/p&gt;

&lt;p&gt;Another approach is to simulate real user behavior. Instead of scraping the entire HTML, focus on specific sections of the page where the data is located. Mimicking real interactions, like clicking on visible elements or navigating the page, helps your scraper appear more human-like and prevents it from interacting with invisible elements that a user wouldn’t be aware of.&lt;/p&gt;

&lt;p&gt;Here’s an example of how you could modify the Hacker News scraper from the earlier section to filter out Honeypot traps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CheerioCrawler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Dataset&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crawlee&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crawler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CheerioCrawler&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;requestHandler&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;enqueueLinks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;log&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Processing &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;...`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Function to check if an element is visible (filter out Honeypots)&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isElementVisible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;css&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;display&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visibility&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;opacity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;height&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;]);&lt;/span&gt;
            &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
                &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;visibility&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
                &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;opacity&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="c1"&gt;// Extract data using Cheerio while avoiding Honeypot traps&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.athing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;isElementVisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;$element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.title a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                    &lt;span class="na"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.rank&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                    &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.title a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="p"&gt;};&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Store the results to the default dataset.&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pushData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Find a link to the next page and enqueue it if it exists.&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;infos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;enqueueLinks&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.morelink&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;infos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;processedRequests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is the last page!`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crawler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addRequests&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://news.ycombinator.com/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// Run the crawler and wait for it to finish.&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crawler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Crawler finished.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;CAPTCHAs
CAPTCHAs, or Completely Automated Public Turing tests to tell Computers and Humans Apart, are those familiar challenges we’ve all seen, clicking on traffic lights or selecting crosswalks in image grids. While frustrating for humans, they are designed to block bots, making them one of the toughest obstacles for scrapers. Encountering one during scraping can bring your process to a halt, as bots can’t solve these puzzles on their own.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The good news is that much of what we’ve already covered, like &lt;a href="https://blog.apify.com/crawl-without-getting-blocked/" rel="noopener noreferrer"&gt;avoiding honeypot traps, rotating IPs, and making your scraper mimic human behavior&lt;/a&gt;, also helps reduce the chances of triggering CAPTCHAs. Websites generally try to show CAPTCHAs only when the activity looks suspicious. By blending in with regular traffic through techniques like rotating IPs, randomizing interactions, and managing request patterns thoughtfully, your scraper can often bypass CAPTCHAs entirely.&lt;/p&gt;

&lt;p&gt;However, CAPTCHAs can still appear, even when precautions are in place. In such cases, your best bet is to integrate a CAPTCHA-solving service. Tools like Apify’s &lt;a href="https://apify.com/petr_cermak/anti-captcha-recaptcha" rel="noopener noreferrer"&gt;Anti Captcha Recaptcha Actor&lt;/a&gt;, which works with &lt;a href="https://anti-captcha.com/" rel="noopener noreferrer"&gt;Anti-Captcha&lt;/a&gt;, can help you equip your crawlers with CAPTCHA-solving capabilities to handle these challenges automatically and avoid disrupting your scraping.&lt;/p&gt;

&lt;p&gt;Here is an example of how you could use the Apify API to integrate the Anti Captcha Recaptcha Actor into your code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApifyClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apify-client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Initialize the ApifyClient with API token&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApifyClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Prepare Actor input&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cookies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name=value; name2=value2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;anticaptcha-key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;proxyAddress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;8.8.8.8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;proxyLogin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;theLogin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;proxyPassword&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;thePassword&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;proxyPort&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;proxyType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;siteKey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;6LfD3PIbAAAAAJs_eEHvoOl75_83eXSqpPSRFJ_u&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userAgent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Opera 6.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;webUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://2captcha.com/demo/recaptcha-v2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Run the Actor and wait for it to finish&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;petr_cermak/anti-captcha-recaptcha&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Data storage and organization
&lt;/h2&gt;

&lt;p&gt;Storing and organizing data effectively is often overlooked in smaller projects but is actually a core component of any successful web scraping operation.&lt;/p&gt;

&lt;p&gt;While collecting data is the first step, how you store, access, and present it has a huge impact on its usability and scalability. Web scraping generates a mix of data types, from structured information like prices and reviews to unstructured content like PDFs and images. This variety demands flexible storage solutions. For small projects, simple CSV or JSON files stored locally might work, but as your needs grow, these methods can quickly fall short.&lt;/p&gt;

&lt;p&gt;For larger datasets or ongoing scraping, cloud-based solutions like &lt;a href="https://www.mongodb.com/" rel="noopener noreferrer"&gt;MongoDB&lt;/a&gt;, &lt;a href="https://aws.amazon.com/" rel="noopener noreferrer"&gt;Amazon S3&lt;/a&gt; or &lt;a href="https://apify.com/storage" rel="noopener noreferrer"&gt;Apify Storage&lt;/a&gt; become necessary. They’re designed to handle large volumes of data and offer quick querying capabilities.&lt;/p&gt;

&lt;p&gt;One standout advantage of &lt;a href="https://apify.com/storage" rel="noopener noreferrer"&gt;Apify Storage&lt;/a&gt; is that it’s specifically designed to meet the needs of web scraping. It offers Datasets for structured data, Key-Value Stores for storing metadata or configurations, and Request Queues to help manage and track your scraping workflows. It integrates seamlessly with tools like Crawlee, provides API access for straightforward data retrieval and management, and supports exporting data in multiple formats.&lt;/p&gt;

&lt;p&gt;Best of all, Apify Storage is just one piece of the comprehensive Apify platform, which delivers a full-stack solution for all your web scraping needs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ycky6muzpocyjz216v8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ycky6muzpocyjz216v8.png" alt=" " width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Automation and monitoring
&lt;/h2&gt;

&lt;p&gt;Manually running scrapers every time you need fresh data is not practical, especially for projects requiring regular updates like price tracking, market research, or monitoring real-time changes.&lt;/p&gt;

&lt;p&gt;Automation ensures your workflows run on schedule, minimizing errors and keeping your data current, while monitoring helps detect and address issues like failed requests, CAPTCHAs, or website structure changes before they cause disruptions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.apify.com/platform/monitoring" rel="noopener noreferrer"&gt;Apify Platform Monitoring&lt;/a&gt; simplifies this process by providing tools specifically designed for automating and monitoring web scraping workflows. With task scheduling, you can set your scrapers to run at specific intervals, ensuring consistent data updates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqy82h2sk3qfw0rp1z04f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqy82h2sk3qfw0rp1z04f.png" alt=" " width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As well as helping you automate scraping, Apify offers monitoring features to view task statuses, detailed logs, and error messages. These features keep you informed about your scraper’s performance, including notifications and alerts, which can be configured to inform you of task completions or errors via email, Slack, or other integrations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0nw017pc4jkziffk03g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0nw017pc4jkziffk03g.png" alt=" " width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Scalability and reliability
&lt;/h2&gt;

&lt;p&gt;Building a scalable and reliable scraping operation relies on the key principles we’ve covered: avoiding blocks, maintaining data consistency, storing collected data efficiently, and automating tasks with proper monitoring. Together, these elements create a solid foundation for a system that can grow with your needs while ensuring quality and performance remain intact.&lt;/p&gt;

&lt;p&gt;One crucial yet often overlooked aspect of scalability is infrastructure management. Handling your own servers can quickly turn into a costly and time-consuming challenge, especially as your project expands. That’s why choosing a robust cloud-based solution like Apify from the very start of your project is a smart choice. Designed for scalability, it automatically adjusts to your project’s needs, so you never have to worry about provisioning servers or hitting capacity limits. You only pay for what you use, keeping costs manageable while ensuring your scrapers keep running without interruption.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://console.apify.com/sign-up" rel="noopener noreferrer"&gt;Get a free Apify plan now!&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  10. Real-time data scraping
&lt;/h2&gt;

&lt;p&gt;The idea behind real-time data scraping is to continuously collect data as soon as it becomes available. This is often a critical requirement for projects involving time-sensitive data, such as stock market analysis, price monitoring, news aggregation, and tracking live trends.&lt;/p&gt;

&lt;p&gt;To achieve this, you need to &lt;a href="https://docs.apify.com/academy/deploying-your-code/deploying" rel="noopener noreferrer"&gt;deploy your code to a cloud platform&lt;/a&gt; and automate your scraping process with a proper schedule. For example, you can deploy your scraping script as an Apify Actor and schedule it to run at intervals that match how “fresh” you need the data to be. Apify’s scheduling and monitoring tools make it easy for you to implement this automation, ensuring a constant flow of real-time data while helping you promptly handle any errors to maintain accuracy and reliability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;And here we are at the end of the article. I hope you’ve found it helpful and can use it as a reference when dealing with the challenges we’ve discussed. Of course, every scraping project is unique, and it’s impossible to cover every scenario in one post. That’s where the value of a strong developer community comes in.&lt;/p&gt;

&lt;p&gt;Connecting with other developers who have faced and solved similar challenges can make a big difference. It’s a chance to exchange ideas, get advice, and share your own experiences.&lt;/p&gt;

&lt;p&gt;If you haven’t already, I encourage you to &lt;a href="https://discord.com/invite/jyEM2PRvMU" rel="noopener noreferrer"&gt;join the Apify &amp;amp; Crawlee Developer Community on Discord&lt;/a&gt;. It’s a great space to learn, collaborate, and grow alongside others who share your interest in web scraping.&lt;/p&gt;

&lt;p&gt;Hope to see you there!&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>crawlee</category>
      <category>antiscraping</category>
    </item>
    <item>
      <title>11 best open-source web crawlers and scrapers in 2024</title>
      <dc:creator>Dávid Lukáč</dc:creator>
      <pubDate>Tue, 29 Oct 2024 14:33:22 +0000</pubDate>
      <link>https://dev.to/apify/11-best-open-source-web-crawlers-and-scrapers-in-2024-16pe</link>
      <guid>https://dev.to/apify/11-best-open-source-web-crawlers-and-scrapers-in-2024-16pe</guid>
      <description>&lt;p&gt;Free software libraries, packages, and SDKs for web crawling? Or is it a web scraper that you need?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hey, we're &lt;a href="https://apify.com/pricing" rel="noopener noreferrer"&gt;Apify&lt;/a&gt;. You can build, deploy, share, and monitor your scrapers and crawlers on the Apify platform. &lt;a href="https://apify.it/platform-pricing" rel="noopener noreferrer"&gt;Check us out&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're tired of the limitations and costs of proprietary &lt;a href="https://blog.apify.com/best-web-scraping-tools/" rel="noopener noreferrer"&gt;web scraping tools&lt;/a&gt; or being locked into a single vendor, open-source web crawlers and scrapers offer a flexible, customizable alternative.&lt;/p&gt;

&lt;p&gt;But not all open-source tools are the same.&lt;/p&gt;

&lt;p&gt;Some are full-fledged libraries capable of handling large-scale &lt;a href="https://blog.apify.com/web-data-extraction/" rel="noopener noreferrer"&gt;data extraction&lt;/a&gt; projects, while others excel at &lt;a href="https://blog.apify.com/what-is-a-dynamic-page/" rel="noopener noreferrer"&gt;dynamic content&lt;/a&gt; or are ideal for smaller, lightweight tasks. The right tool depends on your project’s complexity, the type of data you need, and your preferred programming language.&lt;/p&gt;

&lt;p&gt;The libraries, frameworks, and SDKs we cover here take into account the diverse needs of developers, so you can choose a tool that meets your requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are open-source web crawlers and web scrapers?
&lt;/h2&gt;

&lt;p&gt;Open-source web crawlers and scrapers let you adapt code to your needs without the cost of licenses or restrictions. Crawlers gather broad data, while scrapers target specific information. Open-source solutions like the ones below offer community-driven improvements, flexibility, and scalability—free from vendor lock-in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Top 11 open-source web crawlers and scrapers in 2024
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Crawlee
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Language:&lt;/strong&gt; Node.js, Python | GitHub: 15.4K+ stars | &lt;a href="https://github.com/apify/crawlee" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Crawlee is a complete web scraping and browser automation library designed for quickly and efficiently building reliable crawlers. With built-in anti-blocking features, it makes your bots look like real human users, &lt;a href="https://blog.apify.com/crawl-without-getting-blocked/" rel="noopener noreferrer"&gt;reducing the likelihood of getting blocked.&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn4qrz5pe5ow097063ioo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn4qrz5pe5ow097063ioo.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Available in both &lt;a href="https://crawlee.dev/?__hstc=160404322.72540665235755e5af5a21367ab1294a.1713784601604.1730191216477.1730206072795.287&amp;amp;__hssc=160404322.1.1730206072795&amp;amp;__hsfp=3227366388&amp;amp;_gl=1*bl1l4a*_gcl_aw*R0NMLjE3MjU2MTE1OTEuQ2owS0NRancwT3EyQmhDQ0FSSXNBQTVodWJVMDVaYVVXd291ZmtZMzhCY2pGMmpadFdBandUa1Q3YmNWZHY0dHZuSVQ1aUF5R2Zva2tySWFBdl81RUFMd193Y0I.*_gcl_au*MjA3NDM2MDE2Ni4xNzI5NTA0MzkyLjE4MDExMDkzMzguMTcyOTg0OTE5NC4xNzI5ODQ5NDAw*_ga*MTYzNDgwNjc5NC4xNzEzNzg4OTYz*_ga_62P18XN9NS*MTczMDIwNjA3MS4zMTIuMS4xNzMwMjA2NTU5LjMxLjAuMA.." rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; and &lt;a href="https://crawlee.dev/python?__hstc=160404322.72540665235755e5af5a21367ab1294a.1713784601604.1730191216477.1730206072795.287&amp;amp;__hssc=160404322.1.1730206072795&amp;amp;__hsfp=3227366388&amp;amp;_gl=1*bl1l4a*_gcl_aw*R0NMLjE3MjU2MTE1OTEuQ2owS0NRancwT3EyQmhDQ0FSSXNBQTVodWJVMDVaYVVXd291ZmtZMzhCY2pGMmpadFdBandUa1Q3YmNWZHY0dHZuSVQ1aUF5R2Zva2tySWFBdl81RUFMd193Y0I.*_gcl_au*MjA3NDM2MDE2Ni4xNzI5NTA0MzkyLjE4MDExMDkzMzguMTcyOTg0OTE5NC4xNzI5ODQ5NDAw*_ga*MTYzNDgwNjc5NC4xNzEzNzg4OTYz*_ga_62P18XN9NS*MTczMDIwNjA3MS4zMTIuMS4xNzMwMjA2NTU5LjMxLjAuMA.." rel="noopener noreferrer"&gt;Python&lt;/a&gt;, Crawlee offers a unified interface that supports HTTP and headless browser crawling, making it versatile for various scraping tasks. It integrates with libraries like Cheerio and &lt;a href="https://blog.apify.com/how-to-parse-html-in-python/" rel="noopener noreferrer"&gt;Beautiful Soup for efficient HTML parsing&lt;/a&gt; and headless browsers like Puppeteer and &lt;a href="https://blog.apify.com/scrape-dynamic-websites-with-python/" rel="noopener noreferrer"&gt;Playwright for JavaScript rendering.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The library excels in scalability, automatically managing concurrency based on system resources, &lt;a href="https://blog.apify.com/rotating-proxies/" rel="noopener noreferrer"&gt;rotating proxies to enhance efficiency&lt;/a&gt;, and employing human-like browser fingerprints to avoid detection. Crawlee also ensures robust data handling through persistent URL queuing and pluggable storage for data and files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://crawlee.dev/" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;Check out Crawlee&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy switching between simple HTTP request/response handling and complex JavaScript-heavy pages by changing just a few lines of code.&lt;/li&gt;
&lt;li&gt;Built-in sophisticated anti-blocking features like proxy rotation and generation of human-like fingerprints.&lt;/li&gt;
&lt;li&gt;Integrating tools for common tasks like link extraction, infinite scrolling, and blocking unwanted assets, along with support for both Cheerio and JSDOM, provides a comprehensive scraping toolkit right out of the box.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Its comprehensive feature set and the requirement to understand HTTP and browser-based scraping can create a steep learning curve.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🟧 &lt;a href="https://blog.apify.com/crawlee-web-scraping-tutorial/" rel="noopener noreferrer"&gt;Crawlee web scraping tutorial for Node.js&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Crawlee is ideal for developers and teams seeking to manage simple and complex web scraping and automation tasks in JavaScript/TypeScript and Python. It is particularly effective for scraping web applications that combine static and dynamic pages, as it allows easy switching between different types of crawlers to handle each scenario. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://console.apify.com/sign-up" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;Deploy your scraping code to the cloud&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Scrapy
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Language:&lt;/strong&gt; Python | GitHub: 52.9k stars | &lt;a href="https://github.com/scrapy/scrapy" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scrapy is one of the most complete and popular &lt;a href="https://blog.apify.com/what-is-web-scraping/" rel="noopener noreferrer"&gt;web scraping&lt;/a&gt; frameworks within the Python ecosystem. It is written using Twisted, an event-driven networking framework, giving Scrapy asynchronous capabilities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6kdxyqefyhlty3mvncp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6kdxyqefyhlty3mvncp.png" alt=" " width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a comprehensive &lt;a href="https://blog.apify.com/web-crawling-vs-web-scraping/" rel="noopener noreferrer"&gt;web crawling&lt;/a&gt; framework designed specifically for data extraction, Scrapy provides built-in support for handling requests, processing responses, and exporting data in multiple formats, including CSV, JSON, and XML.&lt;/p&gt;

&lt;p&gt;Its main drawback is that it cannot natively handle dynamic websites. However, you can &lt;a href="https://blog.apify.com/scrapy-playwright/" rel="noopener noreferrer"&gt;configure Scrapy with a browser automation tool like Playwright&lt;/a&gt; or Selenium to unlock these capabilities.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;a href="https://blog.apify.com/web-scraping-with-scrapy/" rel="noopener noreferrer"&gt;Learn more about using Scrapy for web scraping&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Significant performance boost due to its asynchronous nature.&lt;/li&gt;
&lt;li&gt;Specifically designed for web scraping, providing a robust foundation for such tasks.&lt;/li&gt;
&lt;li&gt;Extensible &lt;a href="https://blog.apify.com/scrapy-middleware/" rel="noopener noreferrer"&gt;middleware architecture&lt;/a&gt; makes adjusting Scrapy’s capabilities to fit various scraping scenarios easy.&lt;/li&gt;
&lt;li&gt;Supported by a well-established community with a wealth of resources available online.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Steep learning curve, which can be challenging for less experienced web scraping developers.&lt;/li&gt;
&lt;li&gt;Lacks the ability to handle content generated by JavaScript natively, requiring integration with tools like Selenium or Playwright to scrape dynamic pages.&lt;/li&gt;
&lt;li&gt;More complex than necessary for simple and small-scale scraping tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Scrapy is ideally suited for developers, data scientists, and researchers embarking on large-scale web scraping projects who require a reliable and scalable solution for extracting and processing vast amounts of data.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Run multiple Scrapy spiders in the cloud&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.apify.com/cli/docs/integrating-scrapy" rel="noopener noreferrer"&gt;Read the docs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3.MechanicalSoup
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Language:&lt;/strong&gt; Python | GitHub: 4.7K+ stars | &lt;a href="https://github.com/MechanicalSoup/MechanicalSoup" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MechanicalSoup is a Python library designed to automate website interactions. It provides a simple API to access and interact with HTML content, similar to interacting with web pages through a web browser, but programmatically. MechanicalSoup essentially combines the best features of libraries like Requests for HTTP requests and Beautiful Soup for HTML parsing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbshzbw663nkcome2ytc7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbshzbw663nkcome2ytc7.png" alt=" " width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, you might wonder when to use MechanicalSoup over the traditional combination of BS4+ Requests. MechanicalSoup provides some distinct features &lt;a href="https://blog.apify.com/mechanicalsoup-tutorial/" rel="noopener noreferrer"&gt;particularly useful for specific web scraping tasks.&lt;/a&gt; These include submitting forms, handling login authentication, navigating through pages, and extracting data from HTML.&lt;/p&gt;

&lt;p&gt;MechanicalSoup makes it possible by creating a &lt;code&gt;StatefulBrowser&lt;/code&gt; object in Python that can store cookies and session data and handle other aspects of a browsing session.&lt;/p&gt;

&lt;p&gt;However, while MechanicalSoup offers some browser-like functionalities akin to what you'd expect from a browser automation tool such as Selenium, it does so without launching an actual browser. This approach has its advantages but also comes with certain limitations, which we'll explore next:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Great choice for simple automation tasks such as filling out forms and scraping data from pages that do not require JavaScript rendering.&lt;/li&gt;
&lt;li&gt;Lightweight tool that interacts with web pages through requests without a graphical browser interface. This makes it faster and less demanding on system resources.&lt;/li&gt;
&lt;li&gt;Directly integrates Beautiful Soup, offering all the benefits you would expect from BS4, plus some extra features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unlike real browser automation tools like Playwright and Selenium, MechanicalSoup cannot execute JavaScript. Many modern websites require JavaScript for dynamic content loading and user interactions, which MechanicalSoup cannot handle.&lt;/li&gt;
&lt;li&gt;Unlike Selenium and Playwright, MechanicalSoup does not support advanced browser interactions such as moving the mouse, dragging and dropping, or keyboard actions that might be necessary to retrieve dates from more complex websites.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; MechanicalSoup is a more efficient and lightweight option for more basic scraping tasks, especially for static websites and those with straightforward interactions and navigation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🍲 &lt;a href="https://blog.apify.com/mechanicalsoup-tutorial/" rel="noopener noreferrer"&gt;Learn more about MechanicalSoup&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4. Node Crawler
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Language:&lt;/strong&gt; Node.js  | GitHub: 6.7K+ stars | &lt;a href="https://github.com/bda-research/node-crawler" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Node Crawler, often referred to as 'Crawler,' is a popular web crawling library for Node.js. At its core, Crawler utilizes Cheerio as the default parser, but it can be configured to use JSDOM if needed. The library offers a wide range of customization options, including robust queue management that allows you to enqueue URLs for crawling while it manages concurrency, rate limiting, and retries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2gpkzblwaeu2tdwe7a2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2gpkzblwaeu2tdwe7a2.png" alt=" " width="721" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Built on Node.js, Node Crawler excels at efficiently handling multiple, simultaneous web requests, which makes it ideal for high-volume web scraping and crawling.&lt;/li&gt;
&lt;li&gt;Integrates directly with Cheerio (a fast, flexible, and lean implementation of core jQuery designed specifically for the server), simplifying the process of HTML parsing and data extraction.&lt;/li&gt;
&lt;li&gt;Provides extensive options for customization, from user-agent strings to request intervals, making it suitable for a wide range of web crawling scenarios.&lt;/li&gt;
&lt;li&gt;Easy to set up and use, even for those new to Node.js or web scraping.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does not handle JavaScript rendering natively. For dynamic JavaScript-heavy sites, you need to integrate it with something like Puppeteer or a &lt;a href="https://blog.apify.com/headless-browsers-what-are-they-and-how-do-they-work/" rel="noopener noreferrer"&gt;headless browser&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;While Node Crawler simplifies many tasks, the asynchronous model and event-driven architecture of Node.js can present a learning curve for those unfamiliar with such patterns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Node Crawler is a great choice for developers familiar with the Node.js ecosystem who need to handle large-scale or high-speed web scraping tasks. It provides a flexible solution for web crawling that leverages the strengths of Node.js's asynchronous capabilities.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📖 &lt;a href="https://blog.apify.com/mechanicalsoup-tutorial/" rel="noopener noreferrer"&gt;Related: Web scraping with Node.js guide&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  5. Selenium
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Language:&lt;/strong&gt; Multi-language | GitHub: 30.6K stars | &lt;a href="https://github.com/SeleniumHQ/selenium" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Selenium is a widely-used open-source framework for automating web browsers. It allows developers to write scripts in various programming languages to control browser actions. This makes it suitable for crawling and scraping dynamic content. Selenium provides a rich API that supports multiple browsers and platforms, so you can simulate user interactions like clicking buttons, filling forms, and navigating between pages. Its ability to handle JavaScript-heavy websites makes it particularly valuable for scraping modern web applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5oylhhk9dpocsocegm9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5oylhhk9dpocsocegm9f.png" alt=" " width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cross-browser support:&lt;/strong&gt; Works with all major browsers (Chrome, Firefox, Safari, etc.), allowing for extensive testing and scraping.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic content handling:&lt;/strong&gt; Capable of interacting with JavaScript-rendered content, making it effective for modern web applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich community and resources:&lt;/strong&gt; A large ecosystem of tools and libraries that enhance its capabilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resource-intensive:&lt;/strong&gt; Running a full browser can consume significant system resources compared to headless solutions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steeper learning curve:&lt;/strong&gt; Requires understanding of browser automation concepts and may involve complex setup for advanced features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Selenium is ideal for developers and testers needing to automate web applications or scrape data from sites that heavily rely on JavaScript. Its versatility makes it suitable for both testing and data extraction tasks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📖 &lt;a href="https://blog.apify.com/web-scraping-with-selenium-and-python/" rel="noopener noreferrer"&gt;Related: How to do web scraping with Selenium in Python&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  6. Heritrix
&lt;/h3&gt;

&lt;p&gt;Language: Java | GitHub: 2.8K+ stars | &lt;a href="https://github.com/internetarchive/heritrix3" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Heritrix is open-source web crawling software developed by the Internet Archive. It is primarily used for web archiving - collecting information from the web to build a digital library and support the Internet Archive's preservation efforts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpjqrmycqeb00sqiirxrg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpjqrmycqeb00sqiirxrg.png" alt=" " width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optimized for large-scale web archiving, making it ideal for institutions like libraries and archives needing to preserve digital content systematically.&lt;/li&gt;
&lt;li&gt;Detailed configuration options that allow users to customize crawl behavior deeply, including deciding which URLs to crawl, how to treat them, and how to manage the data collected.&lt;/li&gt;
&lt;li&gt;Able to handle large datasets, which is essential for archiving significant web portions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As it is written in Java, running Heritrix might require more substantial system resources than lighter, script-based crawlers, and it might limit usability for those unfamiliar with Java.&lt;/li&gt;
&lt;li&gt;Optimized for capturing and preserving web content rather than extracting data for immediate analysis or use.&lt;/li&gt;
&lt;li&gt;Does not render JavaScript, which means it cannot capture content from websites that rely heavily on JavaScript for dynamic content generation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Heritrix is best suited for organizations and projects that aim to archive and preserve digital content on a large scale, such as libraries, archives, and other cultural heritage institutions. Its specialized nature makes it an excellent tool for its intended purpose but less adaptable for more general web scraping needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Apache Nutch
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Language:&lt;/strong&gt; Java | GitHub: 2.9K+ stars | &lt;a href="https://github.com/apache/nutch" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Apache Nutch is an extensible open-source web crawler often used in fields like data analysis. It can fetch content through protocols such as HTTPS, HTTP, or FTP and extract textual information from document formats like HTML, PDF, RSS, and ATOM.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F22mfcswqw3ffwiqf3bec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F22mfcswqw3ffwiqf3bec.png" alt=" " width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Highly reliable for continuous, extensive crawling operations given its maturity and focus on enterprise-level crawling.&lt;/li&gt;
&lt;li&gt;Being part of the Apache project, Nutch benefits from strong community support, continuous updates, and improvements.&lt;/li&gt;
&lt;li&gt;Seamless integration with Apache Solr and other Lucene-based search technologies, making it a robust backbone for building search engines.&lt;/li&gt;
&lt;li&gt;Leveraging Hadoop allows Nutch to efficiently process large volumes of data, which is crucial for processing the web at scale.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up Nutch and integrating it with Hadoop can be complex and daunting, especially for those new to these technologies.&lt;/li&gt;
&lt;li&gt;Overly complicated for simple or small-scale crawling tasks, whereas lighter, more straightforward tools could be more effective.&lt;/li&gt;
&lt;li&gt;Since Nutch is written in Java, it requires a Java environment, which might not be ideal for environments focused on other technologies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Apache Nutch is ideal for organizations building large-scale search engines or collecting and processing vast amounts of web data. Its capabilities are especially useful in scenarios where scalability, robustness, and integration with enterprise-level search technologies are required.&lt;/p&gt;

&lt;h3&gt;
  
  
  8.Webmagic
&lt;/h3&gt;

&lt;p&gt;Language: Java | GitHub: 11.4K+ stars | &lt;a href="https://github.com/code4craft/webmagic" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Webmagic is an open-source, simple, and flexible Java framework dedicated to web scraping. Unlike large-scale data crawling frameworks like Apache Nutch, WebMagic is designed for more specific, targeted scraping tasks, which makes it suitable for individual and enterprise users who need to extract data from various web sources efficiently.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3nh5arogcm1twjghch2l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3nh5arogcm1twjghch2l.png" alt=" " width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easier to set up and use than more complex systems like Apache Nutch, designed for broader web indexing and requires more setup.&lt;/li&gt;
&lt;li&gt;Designed to be efficient for small to medium-scale scraping tasks, providing enough power without the overhead of larger frameworks.&lt;/li&gt;
&lt;li&gt;For projects already within the Java ecosystem, integrating WebMagic can be more seamless than integrating a tool from a different language or platform.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Being Java-based, it might not appeal to developers working with other programming languages who prefer libraries available in their chosen languages.&lt;/li&gt;
&lt;li&gt;WebMagic does not handle JavaScript rendering natively. For dynamic content loaded by JavaScript, you might need to integrate with headless browsers, which can complicate the setup.&lt;/li&gt;
&lt;li&gt;While it has good documentation, the community around WebMagic might not be as large or active as those surrounding more popular frameworks like Scrapy, potentially affecting the future availability of third-party extensions and support.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; WebMagic is a suitable choice for developers looking for a straightforward, flexible Java-based web scraping framework that balances ease of use with sufficient power for most web scraping tasks. It's particularly beneficial for users within the Java ecosystem who need a tool that integrates smoothly into larger Java applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Nokogiri
&lt;/h3&gt;

&lt;p&gt;Language: Ruby | GitHub: 6.1K+ stars | &lt;a href="https://github.com/sparklemotion/nokogiri" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Like Beautiful Soup, Nokogiri is also great at parsing HTML and XML documents via the programming language Ruby. Nokogiri relies on native parsers such as the libxml2 libxml2, libgumbo, and xerces. If you want to read or edit an XML document using Ruby programmatically, Nokogiri is the way to go.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9y6ou2ql0xc1zcqbo21k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9y6ou2ql0xc1zcqbo21k.png" alt=" " width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Due to its underlying implementation in C (libxml2 and libxslt), Nokogiri is extremely fast, especially compared to pure Ruby libraries.&lt;/li&gt;
&lt;li&gt;Able to handle both HTML and XML with equal proficiency, making it suitable for a wide range of tasks, from web scraping to RSS feed parsing.&lt;/li&gt;
&lt;li&gt;Straightforward and intuitive API for performing complex parsing and querying tasks.&lt;/li&gt;
&lt;li&gt;Strong, well-maintained community ensures regular updates and good support through forums and documentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Specific to Ruby, which might not be suitable for those working in other programming environments.&lt;/li&gt;
&lt;li&gt;Installation can sometimes be problematic due to its dependencies on native C libraries.&lt;/li&gt;
&lt;li&gt;Can be relatively heavy regarding memory usage, especially when dealing with large documents.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Nokogiri is particularly well-suited for developers already working within the Ruby ecosystem and needs a robust, efficient tool for parsing and manipulating HTML and XML data. Its speed, flexibility, and Ruby-native design make it an excellent choice for a wide range of web data extraction and transformation tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Playwright
&lt;/h3&gt;

&lt;p&gt;Language: Multi-language | GitHub: 67K+ stars| &lt;a href="https://github.com/microsoft/playwright" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Playwright&lt;/strong&gt; an open-source Node.js library introduced in 2020, is widely used for automated browser testing and web scraping. It is cross-platform, supports multiple languages like TypeScript, JavaScript, Python, and Java, and works with Chromium, Firefox, and Webkit. Playwright offers unique features for web automation, including headless mode, autowaits, browser contexts, authentication state persistence, and custom selector engines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8v7l56mztdkayhs6uk01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8v7l56mztdkayhs6uk01.png" alt=" " width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Playwright supports multiple browsers including Chromium, Firefox, and WebKit, for consistent scraping across different platforms. It can also be utilized with various programming languages such as JavaScript, Python, Java, and .NET, which makes it accessible to a broader range of developers.&lt;/li&gt;
&lt;li&gt;Playwright can operate in headless mode, which reduces resource consumption and allows for faster execution of scraping tasks without a graphical interface. The framework automatically waits for elements to be ready before interacting with them. This reduces the need for manual delays and improves reliability.&lt;/li&gt;
&lt;li&gt;It effectively manages websites that rely on JavaScript and AJAX for content loading, so it's suitable for modern web applications. The framework automatically waits for elements to be ready before interacting with them. This reduces the need for manual delays and improves reliability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running multiple browser instances can consume significant system resources, particularly when scraping large volumes of data.&lt;/li&gt;
&lt;li&gt;While capable, Playwright is primarily designed for browser automation and testing rather than dedicated web crawling, which can complicate extensive scraping tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Playwright is best suited for developers looking to automate interactions with web applications that utilize modern frameworks like React or Angular. Its ability to handle dynamic content makes it ideal for scenarios where traditional HTTP request libraries fall short. It is particularly advantageous in projects that require frequent updates or interactions with complex web interfaces.&lt;/p&gt;

&lt;h3&gt;
  
  
  11. Katana
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Language:&lt;/strong&gt; Go | GitHub: 11.1k | &lt;a href="https://github.com/projectdiscovery/katana" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Katana is a web scraping framework focused on speed and efficiency. Developed by Project Discovery, it is designed to facilitate data collection from websites while providing a strong set of features tailored for security professionals and developers. Katana lets you create custom scraping workflows using a simple configuration format. It supports various output formats and integrates easily with other tools in the security ecosystem, which makes it a versatile choice for web crawling and scraping tasks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2jdwahwfyc5ylp7s89b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2jdwahwfyc5ylp7s89b.png" alt=" " width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High performance:&lt;/strong&gt; Built with efficiency in mind, allowing for fast data collection from multiple sources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensible architecture:&lt;/strong&gt; Easily integrates with other tools and libraries, enhancing its functionality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security-focused features:&lt;/strong&gt; Includes capabilities that cater specifically to the needs of security researchers and penetration testers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Limited community support:&lt;/strong&gt; As a newer tool, it does not have as extensive resources or community engagement as more established frameworks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Niche use case focus:&lt;/strong&gt; Primarily designed for security professionals, which may limit its appeal for general-purpose web scraping tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Katana is best suited for security professionals and developers looking for a fast, efficient framework tailored to web scraping needs within the cybersecurity domain. Its integration capabilities make it particularly useful in security testing scenarios where data extraction is required.&lt;/p&gt;

&lt;h2&gt;
  
  
  All-in-one crawling and scraping solution: Apify
&lt;/h2&gt;

&lt;p&gt;Apify is a full-stack web scraping and browser automation platform for building crawlers and scrapers in any programming language. It provides infrastructure for successful scraping at scale: storage, integrations, scheduling, proxies, and more.&lt;/p&gt;

&lt;p&gt;So, whichever library you want to use for your scraping scripts, you can deploy them to the cloud and benefit from all the features the Apify platform has to offer.&lt;/p&gt;

&lt;p&gt;Apify also hosts a library of ready-made data extraction and automation tools (Actors) created by other developers, which you can customize for your use case. That means you don't have to build everything from scratch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ku3d1uzldkhzqglsl2k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ku3d1uzldkhzqglsl2k.png" alt=" " width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://console.apify.com/sign-up" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;Sign up now and start scraping&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>javascript</category>
      <category>python</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to scrape data from any website to Excel</title>
      <dc:creator>Dávid Lukáč</dc:creator>
      <pubDate>Mon, 03 Jul 2023 22:00:00 +0000</pubDate>
      <link>https://dev.to/apify/how-to-scrape-data-from-any-website-to-excel-ibc</link>
      <guid>https://dev.to/apify/how-to-scrape-data-from-any-website-to-excel-ibc</guid>
      <description>&lt;p&gt;&lt;strong&gt;Hi, we're&lt;/strong&gt; &lt;a href="https://apify.it/platform-pricing" rel="noopener noreferrer"&gt;&lt;strong&gt;Apify&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;. The Apify platform gives you access to 1,500+ tools to extract data from popular websites.&lt;/strong&gt; &lt;a href="https://apify.it/platform-pricing" rel="noopener noreferrer"&gt;&lt;strong&gt;Check us out&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.investintech.com/resources/blog/archives/5718-experts-predict-the-future-of-excel-in-business-intelligence.html#:~:text=With%20over%20750%20million%20users,for%20presenting%20and%20analyzing%20data." rel="noopener noreferrer"&gt;Attracting over 750 million users worldwide&lt;/a&gt;, Microsoft Excel is one of the most popular applications for organizing, formatting and calculating data. Excel files are a great example of &lt;a href="https://blog.apify.com/when-data-gets-too-big-why-you-need-structured-data/" rel="noopener noreferrer"&gt;structured data&lt;/a&gt;, allowing users to easily manipulate datasets and gain insight into gathered data thanks to tables, graphs, and other visualizations.&lt;/p&gt;

&lt;p&gt;But if you use Excel a lot, sooner or later, youre probably gonna come across online data that youd like to feed to your table. In this article, well show you four ways you can import any website into a structured Excel file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Manual copy and pasting&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implementing web queries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Excels VBA language&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using web scraping tools&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgnp08ejnsh7r051jw5av.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgnp08ejnsh7r051jw5av.jpg" alt="illustration of a file on one laptop turned to an Excel file on another" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;There are multiple ways of turning a website into an Excel table, some more complicated than others&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Manual copy and pasting&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Depending on the amount and format of the data you want to pull into Excel, manual copying and pasting is always an option - although often a lengthy and tedious one. It is still used in areas such as &lt;a href="https://blog.apify.com/product-matching-ai-pricing-intelligence-web-scraping/#%F0%9F%92%AA-what-about-manual-mapping" rel="noopener noreferrer"&gt;manual product mapping&lt;/a&gt;, which require further interaction and input from the user. It can also be useful when the data you want to extract is already in a table format: for instance, here we simply copy and paste the HTML table from our &lt;a href="https://apify.hashnode.dev/what-are-the-best-python-web-scraping-libraries" rel="noopener noreferrer"&gt;Python libraries&lt;/a&gt; blog article. But keep in mind that the &lt;a href="https://blog.apify.com/when-data-gets-too-big-why-you-need-structured-data/#what-is-big-data-and-why-structured-data-matters" rel="noopener noreferrer"&gt;vast majority of online data is unstructured&lt;/a&gt;, so this method will probably be irrelevant for most use cases.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ltn2hcei7a7ixe4vht6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ltn2hcei7a7ixe4vht6.png" alt="screenshot of a HTML table being copied into Excel" width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Copy and pasting is only effective when the data is already structured&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Implementing web queries&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If youre using Windows, you can use Microsofts &lt;a href="https://powerquery.microsoft.com/en-us/" rel="noopener noreferrer"&gt;Power Query&lt;/a&gt; feature set to get automated structured data straight to your Excel sheet. Simply go to the Data tab, select From Web, and input the URL of the website youd like to export data from. The software will then process the page and find any usable tables that it can pull from the page. After you have the data, you can refresh the query at any time, updating your sheet at the click of a button. While this method is useful for keeping your dataset up to date, it can also only work with data thats already structured. Another disadvantage is that Power Querys ability to get web data is &lt;a href="https://answers.microsoft.com/en-us/msoffice/forum/all/copying-and-pasting-web-tables-into-excel/2f88969c-49ab-4e91-8cb3-4a125c2a9486" rel="noopener noreferrer"&gt;limited to the Windows operating system&lt;/a&gt;, so Mac and other OS users are out of luck here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flikiq3backv0ntx0fndp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flikiq3backv0ntx0fndp.png" alt="screenshot of Excel with the cursor pointing to From Web in the Data section" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;source:&lt;/em&gt; &lt;a href="https://support.microsoft.com/en-au/office/import-data-from-the-web-b13eed81-33fe-410d-9247-1747269c28e4" rel="noopener noreferrer"&gt;&lt;em&gt;Microsoft Support&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Excels VBA language&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Microsofts VBA (&lt;a href="https://learn.microsoft.com/en-us/office/vba/library-reference/concepts/getting-started-with-vba-in-office" rel="noopener noreferrer"&gt;Visual Basic for Applications&lt;/a&gt;) is an implementation of the event-driven programming language Visual Basic into the Office ecosystem. It allows users to access functions beyond what is available in Microsoft Office, letting them automate processes, create macros, custom forms or customize applications to fit their specific business needs. But implementing data extraction into your Excel sheet with VBA requires advanced programming and web scraping knowledge. You will also need to install libraries such as &lt;a href="https://blog.apify.com/web-scraping-with-selenium-and-python/#what-is-selenium" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt; or Microsoft XML HTTP based on if you want to &lt;a href="https://www.youtube.com/watch?v=E3u_1e3wg74&amp;amp;t=75s" rel="noopener noreferrer"&gt;extract data from a webpage that runs scripts&lt;/a&gt;. Since using this method is fundamentally the same as &lt;a href="https://apify.com/web-scraping" rel="noopener noreferrer"&gt;web scraping&lt;/a&gt;, it might be better to use data extraction tools outside of Microsofts ecosystem for a more flexible workflow with more in-depth documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Using web scraping tools&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://blog.apify.com/what-is-web-scraping-and-web-scraping-tools/" rel="noopener noreferrer"&gt;Web scraping&lt;/a&gt; lets you automate the process of data extraction, minimizing the effort put into gathering web data in bulk. Unlike the first two methods, you can scrape any unstructured data from the website, be it product names, prices, headings, descriptions, and so on. This data is then stored in a structured format, and depending on the API youre using to scrape the web, it can also be exported into machine-readable formats such as XLS (Microsoft Excel).&lt;/p&gt;

&lt;p&gt;You can build your own web scraper with &lt;a href="https://blog.apify.com/web-scraping-javascript-nodejs/#http-clients" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; or &lt;a href="https://blog.apify.com/what-are-the-best-python-web-scraping-libraries/" rel="noopener noreferrer"&gt;Python libraries&lt;/a&gt; such as Requests, HTTPX, Selenium, or Playwright, or use pre-made tools where you simply input your desired URL or search query. Apify is a full-stack platform that lets you do both - you can build (&lt;a href="https://docs.apify.com/platform/actors/development/source-code" rel="noopener noreferrer"&gt;or import&lt;/a&gt;) your own scraper with our &lt;a href="https://apify.com/templates" rel="noopener noreferrer"&gt;web scraping templates&lt;/a&gt; or use a ready-made Actor from &lt;a href="https://apify.com/store" rel="noopener noreferrer"&gt;Apify Store&lt;/a&gt; to get the job done.&lt;/p&gt;

&lt;p&gt;So, lets take a look at how you can get data from any website in 3 simple steps using APIs found on Apify Store:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1. Find the right tool&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Apify Store works just like any other app store: just search for an Actor youd like to use based on the website you want to scrape. Most scrapers are free, although you may come across some paid ones - no need to worry; even these offer a free trial without the need for a credit card. After you find your scraper, click the &lt;em&gt;Try for free&lt;/em&gt; button. For this example, were going to be using &lt;a href="https://apify.com/vdrmota/twitter-scraper?ref=blog.apify.com" rel="noopener noreferrer"&gt;Twitter Scraper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmq447ahfmt08w26i0uq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmq447ahfmt08w26i0uq.png" alt="screenshot of Actors on Apify Store" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Find a suitable Actor on&lt;/em&gt; &lt;a href="https://apify.com/store" rel="noopener noreferrer"&gt;&lt;em&gt;Apify Store&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🤔 &lt;a href="https://apify.com/apify/web-scraper" rel="noopener noreferrer"&gt;Cant find the right Actor for your use case? Try out the universal Web scraper, which can extract data from any website after a little bit of setting up&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Youll then be prompted to sign in or make an account if you dont already have one. You can speed up the process by signing in through your Google or GitHub profile.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn5hi41j07jk5u96ryjbq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn5hi41j07jk5u96ryjbq.png" alt="Screenshot of Apify Console's sign up page" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sign in or make an account to access&lt;/em&gt; &lt;a href="https://console.apify.com/" rel="noopener noreferrer"&gt;&lt;em&gt;Apify Console&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2. Choose the data you want to scrape&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now, fill in the input schema to tell your Actor what data you want from the website of your choice. With Twitter Scraper, we decided to scrape the top 30 results from the handle &lt;a href="https://twitter.com/apify?ref=blog.apify.com" rel="noopener noreferrer"&gt;@apify&lt;/a&gt; (yup, were also on Twitter, so dont forget to give us a follow). This feature is especially relevant if you know &lt;a href="https://mailtrap.io/blog/mail-merge-explained/" rel="noopener noreferrer"&gt;how to use mail merge&lt;/a&gt; and want to gather data that helps you tailor outreach or PR messages, for instance.&lt;/p&gt;

&lt;p&gt;If youre not sure what the individual inputs mean, hover your mouse over the question mark next to them to get an explanation. The Actor readme (you can find this on the Actors page in Apify Store) can also be of great help if you feel lost when filling out the schema.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1e7vdzwidmci845milpz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1e7vdzwidmci845milpz.png" alt="Screenshot of the input schema for Twitter Scraper" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fill out the Actor's input schema&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3. Run the scraper and download your results in Excel&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After youre done filling out the input, hit &lt;strong&gt;Save &amp;amp; Start&lt;/strong&gt; to kick off the Actor run. Now just wait for the scrape to finish.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7zm2ub7favm339otf4o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7zm2ub7favm339otf4o.png" alt="Screenshot of an Apify Actor running" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can watch your results load in the Output tab&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As soon your run is finished, you can hit the &lt;strong&gt;Export results&lt;/strong&gt; button at the bottom of the UI. Here you can choose your desired output format (in our case Excel) and which fields from the table you want (or dont want) to export.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1txpcjdzi6er1xo3ch0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1txpcjdzi6er1xo3ch0.png" alt="Screenshot of the Export dataset pop-up on Apify Console" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Download your data in an Excel format&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tip: Not every scraper has the &lt;em&gt;Output&lt;/em&gt; / &lt;em&gt;Overview&lt;/em&gt; tab. If thats the case, go to &lt;em&gt;Storage&lt;/em&gt; to get the full data in Excel.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;And thats it! Now that you have your data, its time to explore the world of web scraping with a bigger pool of Actors: Interested in social media? Try our &lt;a href="https://apify.com/jaroslavhejlek/instagram-scraper?ref=blog.apify.com" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://apify.com/clockworks/tiktok-scraper" rel="noopener noreferrer"&gt;TikTok&lt;/a&gt;, or &lt;a href="https://apify.com/comchat/reddit-api-scraper" rel="noopener noreferrer"&gt;Reddit&lt;/a&gt; scrapers. If youd prefer to scrape product listings and their sellers, give the &lt;a href="https://apify.com/vaclavrut/amazon-crawler?ref=blog.apify.com" rel="noopener noreferrer"&gt;Amazon&lt;/a&gt;, &lt;a href="https://apify.com/dtrungtin/ebay-items-scraper?ref=blog.apify.com" rel="noopener noreferrer"&gt;eBay&lt;/a&gt;, or &lt;a href="https://apify.com/epcsht/aliexpress-scraper?ref=blog.apify.com" rel="noopener noreferrer"&gt;AliExpress&lt;/a&gt; scrapers a go. Looking for new hires? Scrape job listings from &lt;a href="https://apify.com/misceres/indeed-scraper" rel="noopener noreferrer"&gt;Indeed&lt;/a&gt; or &lt;a href="https://apify.com/alexey/glassdoor-jobs-scraper?ref=blog.apify.com" rel="noopener noreferrer"&gt;Glassdoor&lt;/a&gt;. You can even further &lt;a href="https://apify.com/integrations" rel="noopener noreferrer"&gt;integrate&lt;/a&gt; these tools with other platforms, to bring your web scraping workflow to the next level 🚀&lt;/p&gt;

&lt;p&gt;Missing an Actor in Apify Store? You can contribute by &lt;a href="https://apify.com/partners/actor-developers" rel="noopener noreferrer"&gt;monetizing your own code&lt;/a&gt; or &lt;a href="https://apify.com/ideas" rel="noopener noreferrer"&gt;publishing an idea&lt;/a&gt; as an inspiration for our developer community. And if you need any advice from web scraping and automation enthusiasts, theres always our &lt;a href="https://discord.com/invite/crawlee-apify-801163717915574323" rel="noopener noreferrer"&gt;Discord channel&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>webscraping</category>
    </item>
    <item>
      <title>What are the highest paying programming languages in 2022?</title>
      <dc:creator>Dávid Lukáč</dc:creator>
      <pubDate>Fri, 04 Nov 2022 14:06:21 +0000</pubDate>
      <link>https://dev.to/apify/what-are-the-highest-paying-programming-languages-in-2022-2imi</link>
      <guid>https://dev.to/apify/what-are-the-highest-paying-programming-languages-in-2022-2imi</guid>
      <description>&lt;p&gt;Based on data provided by employment websites &lt;a href="https://www.glassdoor.com/Salaries/web-developer-salary-SRCH_KO0,13.htm?_gl=1*tmj9i*_ga*MzA2MjkwNzgzLjE2NjQ4MTAyNzc.*_ga_RC95PMVB3H*MTY2NDgxMDI3Ny4xLjEuMTY2NDgxMDI3Ny42MC4wLjA." rel="noopener noreferrer"&gt;Glassdoor&lt;/a&gt; and &lt;a href="https://www.indeed.com/career/software-engineer/salaries?from=top_sb" rel="noopener noreferrer"&gt;Indeed&lt;/a&gt;, web developers in the US make around &lt;a href="https://www.indeed.com/career/web-developer/salaries?&amp;amp;aceid=&amp;amp;kw=adwords_c_9099621460_15516767951_&amp;amp;sid=us_googconthajpmax-_c__g_1003803_gclid%24_Cj0KCQjwkOqZBhDNARIsAACsbfJQjiEc4WUYFHh_mH7SVGoBt3PXUMJTQ4IsV0szndVBVpkt36QHwV8aAjwFEALw_wcB&amp;amp;gclid=Cj0KCQjwkOqZBhDNARIsAACsbfJQjiEc4WUYFHh_mH7SVGoBt3PXUMJTQ4IsV0szndVBVpkt36QHwV8aAjwFEALw_wcB&amp;amp;gclsrc=aw.ds" rel="noopener noreferrer"&gt;$70,000 a year&lt;/a&gt;, while the paychecks of software developers and engineers often exceed the &lt;a href="https://www.glassdoor.com/Salaries/software-developer-salary-SRCH_KO0,18.htm#:~:text=The%20estimated%20total%20pay%20for,salaries%20collected%20from%20our%20users." rel="noopener noreferrer"&gt;$90,000 mark&lt;/a&gt;. Of course, these are just average figures, and real salaries can vary based on &lt;a href="https://content.techgig.com/career-advice/5-factors-that-decide-how-much-salary-do-software-developers-get/articleshow/87461512.cms" rel="noopener noreferrer"&gt;multiple factors&lt;/a&gt;. These include the location of the job, the size and type of company, and, most importantly, the skill set and experience of the developer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.apify.com/how-to-make-money-from-coding/" rel="noopener noreferrer"&gt;💼 Learn more about the types of jobs you can do with your programming skills&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the most important assets of a developers skill set is the programming language(s) they have learned and mastered. Although these are often already picked out by accredited institutions that offer IT-related study programs, you can still choose which courses to attend or self-study any language you like. But choosing the right programming language is not just a matter of its difficulty, popularity, or practicality. When developers enter the job market, it also directly affects the size of their salary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.apify.com/content/images/2022/11/programming_money-2.jpg" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwe3x4capr0h0i7dr87ig.jpg" alt="Ones and zeroes on a glowing screen to demonstrate both coding and the numbers in a developer paycheck" width="800" height="533"&gt;&lt;/a&gt;A job in programming is sure to land you an above-average pay-check&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the highest-paying programming languages?
&lt;/h2&gt;

&lt;p&gt;Thanks to &lt;a href="https://survey.stackoverflow.co/2022/" rel="noopener noreferrer"&gt;Stack Overflows Developer Survey&lt;/a&gt; conducted in 2022, we can get relevant insights into the developer job market, backed by over &lt;a href="https://survey.stackoverflow.co/2022/#methodology-general" rel="noopener noreferrer"&gt;73,000 responses&lt;/a&gt; from programmers worldwide. One of the fields analyzed in the survey is the technology used in the developer workflow and how it's projected onto their paycheck. The sums in their list represent the median yearly salary (including bonuses) before taxes. So, lets take a closer look at the first 5 &lt;a href="https://survey.stackoverflow.co/2022/#technology-top-paying-technologies" rel="noopener noreferrer"&gt;top paying programming, scripting, and markup languages&lt;/a&gt; identified by the survey:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Clojure - $106,644
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://blog.apify.com/content/images/2022/11/clojure_logo.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu10g2hrrma5i1gsu4v4x.png" width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clojure leads the list as the highest-paid programming language. It's part of the Lisp family of languages, typical for its code-as-data approach and powerful macro system. It runs on Java Virtual Machine, and since it is a functional language, all of its functions are compiled to JVM bytecode. As with many other languages on the list, the higher paycheck can be attributed to the limited number of programmers who know how to use it and the seniority of those who do. But even though it sports a smaller fanbase, its still very likable (being the &lt;a href="https://survey.stackoverflow.co/2022/#technology-most-loved-dreaded-and-wanted" rel="noopener noreferrer"&gt;third most-loved language&lt;/a&gt; within the survey) and useful - it's &lt;a href="https://clojure.org/community/success_stories" rel="noopener noreferrer"&gt;implemented in big companies&lt;/a&gt; such as Apple, Netflix, and Walmart.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Erlang - $103,000
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://blog.apify.com/content/images/2022/11/erlang_logo.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gk2fph2csvulxg8i800.png" width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Erlang is an older functional language developed originally for telephone switches and telecommunication systems. Today, it has found its use case in scalable, concurrent systems that require high availability. While it may not be as popular as modern programming languages, it is still used today to power applications such as &lt;a href="https://www.wired.com/2015/09/whatsapp-serves-900-million-users-50-engineers/" rel="noopener noreferrer"&gt;WhatsApp&lt;/a&gt;, where a fast and stable connection between millions of users is a must.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. F# - $95,526
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://blog.apify.com/content/images/2022/11/fsharp_logo.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4j1ifcrtypgh8xzyzse5.png" width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This universal programming language is part of the &lt;a href="https://en.wikipedia.org/wiki/ML_(programming_language)" rel="noopener noreferrer"&gt;ML family&lt;/a&gt; and allows you to write robust, functional, and performant code. It's maintained not only by the F# Software Foundation but also by Microsoft and other open-source contributors. Its mainly viewed as a back-end language, useful for data processing, web APIs, and one-off scripts. &lt;a href="https://fsharpforfunandprofit.com/posts/fvsc-sum-of-squares/" rel="noopener noreferrer"&gt;Compared to C#&lt;/a&gt;, for instance, the code is much shorter since it has less noise, and its functions can stand alone because the language doesnt force the developer into the OOP paradigm.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Lisp - $95,000
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://blog.apify.com/content/images/2022/11/lisp_logo.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furflsgozw6unn8x6r86a.png" width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lisp, or LISP (List Processing Programming Language), is one of the oldest high-level languages and was made primarily for easy manipulation of data strings. Its inception can be dated all the way back to 1958. Since then, many different dialects of Lisp have been formed, such as Clojure, which sits at the top of this list. Nowadays, Lisp is used in diverse fields, such as &lt;a href="https://www.britannica.com/technology/LISP-computer-language" rel="noopener noreferrer"&gt;AI&lt;/a&gt;, thanks to its self-modifying programs, which give applications some learning ability.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Ruby - $93,000
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://blog.apify.com/content/images/2022/11/ruby_logo.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6mmxffbh1achgbhf896.png" width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ruby is a high-level open-source programming language suitable for both front-end and back-end development. Its main goal is to boost developer productivity with its clear syntax. Rubys simplicity is great for both beginners and devs looking to scale their programs. It's primarily used in the back-end with the &lt;a href="https://rubyonrails.org/" rel="noopener noreferrer"&gt;Ruby on Rails framework&lt;/a&gt; to build web applications and automation tools or to create web page templates and write server-side code. Unlike other languages in this list, Ruby is among the &lt;a href="https://survey.stackoverflow.co/2022/#technology-most-popular-technologies" rel="noopener noreferrer"&gt;top 20 most popular programming languages&lt;/a&gt;, so finding a job offer for a Ruby programmer should not be a chore.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Elixir - $92,959
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://blog.apify.com/content/images/2022/11/elixir_logo.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fimf561pa0hxai37shyhr.png" width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Elixir is a dynamic and functional language primarily used for building scalable and maintainable web applications. It builds upon the 2nd highest-paid language - Erlang, and runs on the BEAM virtual machine, which implements the aforementioned language. It was created in 2012 with the &lt;a href="https://blog.bitsrc.io/how-to-learn-elixir-for-hipster-javascript-developers-f0352e579ac3" rel="noopener noreferrer"&gt;purpose of reintroducing 1980s tech&lt;/a&gt; like Erlang, which is used to build distributed, fault-tolerant systems. It is, therefore, prominent in telecommunication, finance, and e-commerce industries.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Scala - $92,780
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://blog.apify.com/content/images/2022/11/scala_logo.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft9i2bq61q9rul3k60uu2.png" width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This high-level object-oriented and functional language was developed as an alternative to Java, with which it shares many similarities. It also runs on Java virtual machine and can be compiled into JavaScript. But in contrast with languages like Ruby, Python, or Lisp, Scala is a &lt;a href="https://www.oreilly.com/library/view/scala-and-spark/9781785280849/ff7c8d1b-871c-4a7c-b332-05070e3359ec.xhtml" rel="noopener noreferrer"&gt;static-typed language&lt;/a&gt;. That makes it perfect for high-volume projects and has the strength to power data engineering infrastructures in many companies.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Perl - $90,073
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://blog.apify.com/content/images/2022/11/perl_logo.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd5t1gzp13xkuy76v9341.png" width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Perl, also known as Practical Extraction and Reporting Language, is a family of two languages: Perl 5 (released in 1987) and its 2000s redesign known as Perl 6, which was recently renamed &lt;a href="https://www.raku.org/" rel="noopener noreferrer"&gt;Raku&lt;/a&gt;. In syntax it's quite similar to languages such as C or Shell. Still, in the context of speed, iterative implementation in C can be up to &lt;a href="https://docstore.mik.ua/orelly/weblinux2/modperl/ch13_12.htm" rel="noopener noreferrer"&gt;56 times faster&lt;/a&gt; than the algorithm implemented in Pearl. But this comparison is mainly relevant in mathematical tasks, and Perl still shines in the context of text manipulation, system administration, or web development.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Go - $89,204
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://blog.apify.com/content/images/2022/11/go_logo_v2.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbumr0nclfd8b2xk1rfox.png" width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This statically-typed open source language was made by Google engineers in 2009. Although Google built it, its development was reminiscent of a &lt;a href="https://go.dev/conduct" rel="noopener noreferrer"&gt;community project&lt;/a&gt; from developers to developers. It was created to be simple to learn and easy to read. But this may also be its biggest drawback since its limitations result in a smaller set of features, especially when compared to languages such as C++, with which it bears similarities. This language is implemented in cloud and server-side applications and other network interfaces.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Rust - $87,047
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://blog.apify.com/content/images/2022/11/rust_logo.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fom3zx87k0jim62sy4ny6.png" width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rust is a low-level statically-typed language. It was released in 2020 and has gained popularity for its performance and safety, which is why it's often used in the back-end for system development and building operation systems or microcontroller applications. It is quite a complex language to learn, with the shift being easier when going from more challenging languages such as C++. But compared to C++ (which is in the bottom half of the list), Rust is ranked as the &lt;a href="https://survey.stackoverflow.co/2022/#most-loved-dreaded-and-wanted-language-love-dread" rel="noopener noreferrer"&gt;no.1 most-loved language&lt;/a&gt; in Stacks survey. So, in the end, it may just be worth the effort!&lt;/p&gt;

&lt;h2&gt;
  
  
  Which programming language is worth learning?
&lt;/h2&gt;

&lt;p&gt;While learning one of the languages above is sure to narrow down your possible job offers to only the best in financial compensation, it might narrow your search a little too much. These languages are often either rare in the modern industry, need a very specific level of expertise, or are aimed mainly at senior developers.&lt;/p&gt;

&lt;p&gt;Therefore, if you dont have time to spare and your priority is to land a job in the programming world, your best bet is to focus on the &lt;a href="https://survey.stackoverflow.co/2022/#technology-most-popular-technologies" rel="noopener noreferrer"&gt;most popular technologies&lt;/a&gt; (&lt;em&gt;technologies&lt;/em&gt; referring to programming, scripting, and markup languages) rather than the best-paid ones. Youll still get paid quite well - JavaScript, for example, is the most popular programming language out there. Its yearly median salary is $65,580, which is already over $10,000 higher than the &lt;a href="https://www.thebalancemoney.com/average-salary-information-for-us-workers-2060808" rel="noopener noreferrer"&gt;average median income in the US&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.apify.com/content/images/2022/11/most_popular_languages.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45rebdmmmlhmp67vpy9y.png" alt="Comparison of JavaScript, HTML and CSS, SQL, Python popularity" width="800" height="205"&gt;&lt;/a&gt;JavaScript is the most popular technology, surpassing giants such as HTML, SQL, and even Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can coding be a side gig?
&lt;/h2&gt;

&lt;p&gt;If youre in school or just want to make some extra money on the side, there are many ways of monetizing your coding skills. You can freelance and take on smaller projects, work part-time, or publish your code on various platforms such as Apify. With Apify, you can &lt;a href="https://get.apify.com/monetize-your-code" rel="noopener noreferrer"&gt;monetize your code&lt;/a&gt; by creating a web scraping or automation service and offering it in &lt;a href="https://apify.com/store" rel="noopener noreferrer"&gt;Apify Store&lt;/a&gt;, charging your users a monthly subscription fee to have access to it. You can also join our rapidly growing &lt;a href="https://docs.google.com/document/d/1htQtQFO97e5uG16-TU1K5sgNVVXcaD6YL1WETNOoSyk/edit#%20What%20are%20the%20highest%20paying%20programming%20languages?" rel="noopener noreferrer"&gt;Discord server&lt;/a&gt;, where you can not only meet and collaborate with web automation enthusiasts from around the world but also take on projects offered by companies and individuals alike as a freelancer.&lt;/p&gt;

&lt;p&gt;So, choosing a programming language should be based not only on the average paycheck that comes with knowing the language but also on its popularity and prominence in the job market. Only after you take the first step and find a job in coding is when itll be much easier to make decisions about the future of your career based on certain salary expectations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apify.com/ideas" rel="noopener noreferrer"&gt;💡 Have an idea of a project for our developers, or is there something youd like to work on at Apify? Let us know on our ideas page and upvote ideas that you may find useful!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>developer</category>
      <category>jobs</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
