<?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: Scrapfly</title>
    <description>The latest articles on DEV Community by Scrapfly (@scrapfly).</description>
    <link>https://dev.to/scrapfly</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%2Forganization%2Fprofile_image%2F6854%2Fb06fdc6a-c155-4d31-af4d-19a72e307cc6.jpg</url>
      <title>DEV Community: Scrapfly</title>
      <link>https://dev.to/scrapfly</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/scrapfly"/>
    <language>en</language>
    <item>
      <title>Comprehensive Guide to OkHttp for Java and Kotlin</title>
      <dc:creator>Scrapfly</dc:creator>
      <pubDate>Thu, 05 Dec 2024 14:20:37 +0000</pubDate>
      <link>https://dev.to/scrapfly/comprehensive-guide-to-okhttp-for-java-and-kotlin-2lgn</link>
      <guid>https://dev.to/scrapfly/comprehensive-guide-to-okhttp-for-java-and-kotlin-2lgn</guid>
      <description>&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fguide-to-okhttp-java-kotlin_banner.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fguide-to-okhttp-java-kotlin_banner.svg" alt="Comprehensive Guide to OkHttp for Java and Kotlin" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When building applications that communicate over the web, a reliable and efficient HTTP client is essential. &lt;a href="https://square.github.io/okhttp/" rel="noopener noreferrer"&gt;OkHttp&lt;/a&gt;, one of the most popular HTTP clients for Java and Android development, stands out as a powerful tool for handling network operations.&lt;/p&gt;

&lt;p&gt;This article will explore OkHttp’s key features, setup instructions, basic usage, advanced functionalities, and common issues you might encounter.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is OkHttp?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;OkHttp&lt;/strong&gt; is an HTTP client designed for both Java and Kotlin, widely recognized for its reliability and performance. It simplifies network communication by providing a consistent interface for making HTTP requests, handling responses, and optimizing network traffic.&lt;/p&gt;

&lt;p&gt;Whether you're developing a mobile app or a backend service, OkHttp offers a robust solution for dealing with HTTP requests and responses &lt;strong&gt;efficiently&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In Android and Java development, OkHttp acts as a modern alternative to other HTTP clients, thanks to its lightweight design and support for features like connection pooling and timeouts. It’s a go-to choice for developers aiming to implement complex network operations with minimal configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Main OkHttp Features
&lt;/h2&gt;

&lt;p&gt;OkHttp offers an impressive range of features designed to enhance network performance and simplify development. Below is a feature table showcasing some of its capabilities:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HTTP/2 Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Enables multiplexed requests for better connection pooling.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Async Requests&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Facilitates non-blocking, parallel network requests.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Interceptors&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Customizes requests and responses (logging, modifying headers).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Built-in Caching&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reduces network usage by caching responses.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Timeouts&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Configurable connection, read, and write timeouts.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HTTPS Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Out-of-the-box HTTPS support with certificate pinning.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compression&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GZIP and deflate for response compression.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Redirect Handling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automatic handling of 3xx HTTP redirects.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;WebSocket Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full support for WebSocket connections.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Authentication Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Basic, Digest, and custom authentication mechanisms.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;While OkHttp covers a wide array of features, there are a few limitations to be aware of. Notably, it lacks built-in retry strategies, and modern conveniences like auto &lt;code&gt;.json()&lt;/code&gt; methods are not natively included. However, these shortcomings can often be mitigated with custom implementations or third-party libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up OkHttp
&lt;/h2&gt;

&lt;p&gt;Setting up OkHttp is straightforward, whether you’re developing a Java application or an Android project. For Java, you can include OkHttp by adding it to your Maven or Gradle build configuration. Below are installation instructions:&lt;/p&gt;

&lt;p&gt;To install okhttp using &lt;strong&gt;Maven&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.squareup.okhttp3&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;okhttp&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;4.12.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To install okhttp using &lt;strong&gt;Java Gradle&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;implementation 'com.squareup.okhttp3:okhttp:4.12.0'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To install okhttp using &lt;strong&gt;Kotlin Gradle&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;implementation("com.squareup.okhttp3:okhttp:4.12.0")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Basic Usage
&lt;/h2&gt;

&lt;p&gt;To get started with OkHttp, let’s explore some basic usage patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  GET Requests and Response Details
&lt;/h3&gt;

&lt;p&gt;Making a simple GET request with OkHttp is simple. Here’s how you can retrieve the response body and status code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;OkHttpClient&lt;/span&gt; &lt;span class="n"&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;OkHttpClient&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&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;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://web-scraping.dev/api/products"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Response&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newCall&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isSuccessful&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Response Body: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;string&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Status Code: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handling Errors
&lt;/h3&gt;

&lt;p&gt;Error handling in OkHttp is critical to ensure smooth user experiences. Common issues such as connection timeouts or 4xx/5xx HTTP errors can be caught and managed using &lt;code&gt;try-catch&lt;/code&gt; blocks. You can also inspect the status code to handle specific HTTP errors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Response&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newCall&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isSuccessful&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IOException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unexpected code "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Synchronous and Asynchronous Requests
&lt;/h3&gt;

&lt;p&gt;OkHttp supports both synchronous and asynchronous requests, providing flexibility based on your application’s needs. The synchronous request waits for the response before proceeding, while the asynchronous request runs in the background.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Synchronous&lt;/span&gt;
&lt;span class="nc"&gt;Response&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newCall&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Asynchronous&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newCall&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;enqueue&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;Callback&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Add callback for success:&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onResponse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Call&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;string&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Add callback for failure:&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onFailure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Call&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advanced Usage
&lt;/h2&gt;

&lt;p&gt;OkHttp also supports a variety of advanced use cases, including different HTTP methods, handling headers and cookies, and configuring timeouts.&lt;/p&gt;

&lt;h3&gt;
  
  
  POST, PUT, HEAD, PATCH Requests
&lt;/h3&gt;

&lt;p&gt;OkHttp allows you to make POST, PUT, HEAD, and PATCH requests with ease. Here’s are basic examples of each:&lt;/p&gt;

&lt;h4&gt;
  
  
  POST
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;RequestBody&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RequestBody&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MediaType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"application/json; charset=utf-8"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"{\"key\":\"value\"}"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&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;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://httpbin.dev/post"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  HEAD
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&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;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://httpbin.dev/head"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;head&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// HEAD request does not require a body&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  PUT
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;RequestBody&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RequestBody&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MediaType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"application/json; charset=utf-8"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"{\"key\":\"updatedValue\"}"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&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;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://httpbin.dev/put"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// PUT request with a body&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  PATCH
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;RequestBody&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RequestBody&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MediaType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"application/json; charset=utf-8"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"{\"key\":\"patchedValue\"}"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&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;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://httpbin.dev/patch"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;patch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// PATCH request with a body&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding Query Parameters
&lt;/h3&gt;

&lt;p&gt;OkHttp provides a straightforward way to add query parameters to your requests without manually building the URL string. Using the HttpUrl.Builder class, you can easily add key-value pairs as query parameters to a URL before making the request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;OkHttpClient&lt;/span&gt; &lt;span class="n"&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;OkHttpClient&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="nc"&gt;HttpUrl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt; &lt;span class="n"&gt;urlBuilder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpUrl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://web-scraping.dev/api/products"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newBuilder&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;urlBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addQueryParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"page"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;urlBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addQueryParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"order"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"desc"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;urlBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addQueryParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"category"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"apparel"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urlBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Building the request with the URL containing query parameters&lt;/span&gt;
&lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&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;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding Headers
&lt;/h3&gt;

&lt;p&gt;You can add custom headers to your requests, like authentication tokens or user-agent strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&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;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://web-scraping.dev/api/products"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addHeader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authorization"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Bearer token"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding Cookies
&lt;/h3&gt;

&lt;p&gt;OkHttp also allows you to manage cookies by using its &lt;code&gt;CookieJar&lt;/code&gt; interface. This enables you to persist cookies between requests or manage them manually.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;OkHttpClient&lt;/span&gt; &lt;span class="n"&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;OkHttpClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cookieJar&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;CookieJar&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;@Override&lt;/span&gt;
            &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;saveFromResponse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpUrl&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Cookie&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Cookie&lt;/span&gt; &lt;span class="n"&gt;cookie&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Saving cookie: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;cookie&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;

            &lt;span class="nd"&gt;@Override&lt;/span&gt;
            &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Cookie&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;loadForRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpUrl&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Empty for this example&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;})&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&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;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://web-scraping.dev/blocked"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding Timeout
&lt;/h3&gt;

&lt;p&gt;OkHttp gives you the ability to configure connection, read, and write timeouts for each HTTP request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;OkHttpClient&lt;/span&gt; &lt;span class="n"&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;OkHttpClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;connectTimeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;TimeUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SECONDS&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Set connection timeout&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writeTimeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;TimeUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SECONDS&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Set write timeout&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readTimeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;TimeUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SECONDS&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Set read timeout&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&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;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://web-scraping.dev/api/products"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding Retries
&lt;/h3&gt;

&lt;p&gt;Although OkHttp doesn’t have built-in retry strategies, you can easily add them yourself by using interceptors or implementing custom logic for retries.&lt;/p&gt;

&lt;p&gt;To implement it using interceptors, we can create a new okhttp interceptor that has the retry logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RetryInterceptor&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Interceptor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;maxRetries&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;RetryInterceptor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;maxRetries&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;maxRetries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;maxRetries&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt; &lt;span class="nf"&gt;intercept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Chain&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;Response&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Attempt the request up to maxRetries times&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;maxRetries&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;proceed&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

                &lt;span class="c1"&gt;// If response is successful, return it&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isSuccessful&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;exception&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;

            &lt;span class="c1"&gt;// Wait before retrying the request (optional delay)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;maxRetries&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 2-second delay between retries&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;InterruptedException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentThread&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;interrupt&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// If all attempts failed, throw the exception&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// If the response is null and maxRetries are exhausted, throw an IOException&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IOException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Maximum retry attempts ("&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;maxRetries&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;") exhausted"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can use this interceptor within our okhttp client builder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;OkHttpClient&lt;/span&gt; &lt;span class="n"&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;OkHttpClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addInterceptor&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;RetryInterceptor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// Add custom retry interceptor&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&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;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://web-scraping.dev/api/products"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Disabling HTTPS
&lt;/h3&gt;

&lt;p&gt;In certain scenarios, you might need to disable HTTPS validation. While this is generally not recommended, it can be done for testing purposes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;OkHttpClient&lt;/span&gt; &lt;span class="n"&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;OkHttpClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sslSocketFactory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;createUnsafeSslSocketFactory&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;X509TrustManager&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Implementation here&lt;/span&gt;
    &lt;span class="o"&gt;})&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  WebSocket
&lt;/h3&gt;

&lt;p&gt;OkHttp makes it simple to work with WebSockets, allowing you to easily connect, send, and receive messages in real-time. In the example below, you will see how to establish a WebSocket connection using OkHttp, send a message to the server, and handle incoming messages asynchronously using &lt;code&gt;WebSocketListener&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;OkHttpClient&lt;/span&gt; &lt;span class="n"&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;OkHttpClient&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&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;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wss://example.com/socket"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="nc"&gt;WebSocketListener&lt;/span&gt; &lt;span class="n"&gt;listener&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;WebSocketListener&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onOpen&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WebSocket&lt;/span&gt; &lt;span class="n"&gt;webSocket&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"WebSocket Opened"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;webSocket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello Server!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WebSocket&lt;/span&gt; &lt;span class="n"&gt;webSocket&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Message from server: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onFailure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WebSocket&lt;/span&gt; &lt;span class="n"&gt;webSocket&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newWebSocket&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispatcher&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;executorService&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;shutdown&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Common OkHttp Errors and Issues
&lt;/h2&gt;

&lt;p&gt;While OkHttp is highly reliable, you may encounter errors from time to time. Some common issues include:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Issue/Exception&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;java.net.SocketTimeoutException&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Occurs when the connection, read, or write operation exceeds the set timeout.&lt;/td&gt;
&lt;td&gt;Increase the timeout duration with &lt;code&gt;.connectTimeout()&lt;/code&gt;, &lt;code&gt;.readTimeout()&lt;/code&gt;, or &lt;code&gt;.writeTimeout()&lt;/code&gt; on &lt;code&gt;OkHttpClient&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;java.net.UnknownHostException&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Indicates that the domain name cannot be resolved by DNS.&lt;/td&gt;
&lt;td&gt;Check network connection, ensure DNS is reachable, or configure a custom DNS with OkHttp.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;java.io.IOException: unexpected end of stream&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Often caused by network disconnection or improper server response.&lt;/td&gt;
&lt;td&gt;Retry the request or ensure server responses are properly formatted.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SSLHandshakeException&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SSL/TLS handshake fails, commonly due to incorrect certificates or unsupported protocols.&lt;/td&gt;
&lt;td&gt;Ensure correct SSL certificates, or set &lt;code&gt;hostnameVerifier&lt;/code&gt; and &lt;code&gt;certificatePinner&lt;/code&gt; if needed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;java.net.ProtocolException&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Indicates a protocol error, such as an invalid HTTP response or request method.&lt;/td&gt;
&lt;td&gt;Verify request setup (e.g., method type, headers) or handle specific protocols.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;java.io.EOFException&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Happens when OkHttp reads an incomplete response body from the server.&lt;/td&gt;
&lt;td&gt;Use interceptors to handle partial responses or consider increasing the read timeout.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;java.net.ConnectException&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Failed to connect to the server, often due to unreachable server or network issues.&lt;/td&gt;
&lt;td&gt;Check server availability, network connection, or retry the connection.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HTTP 413 Payload Too Large&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Server rejects the request due to a large payload.&lt;/td&gt;
&lt;td&gt;Reduce payload size or consult the server for acceptable payload limits.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HTTP 429 Too Many Requests&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Server rate-limiting response due to too many requests in a short period.&lt;/td&gt;
&lt;td&gt;Implement retry logic with backoff or adhere to rate limits.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ResponseBody is null&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Occurs when a request is successful but the server returns no content.&lt;/td&gt;
&lt;td&gt;Check if the endpoint is expected to return data, or handle null &lt;code&gt;ResponseBody&lt;/code&gt; safely.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TimeoutException: A connection timeout occurred&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Appears when establishing the connection takes too long.&lt;/td&gt;
&lt;td&gt;Increase connection timeout or use exponential backoff for retries.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IOException: Cleartext HTTP traffic not permitted&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Occurs on Android when accessing a plain HTTP URL instead of HTTPS.&lt;/td&gt;
&lt;td&gt;Add &lt;code&gt;cleartextTrafficPermitted&lt;/code&gt; in the network security config or switch to HTTPS if possible.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IllegalArgumentException: unexpected url&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Raised when an invalid or malformed URL is used in the request.&lt;/td&gt;
&lt;td&gt;Ensure the URL is correctly formatted and valid.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Power Up With Scrapfly
&lt;/h2&gt;

&lt;p&gt;While OkHTTP can be used for web scraping purposes, you will often find yourself facing blocks and rate-limits.&lt;/p&gt;

&lt;p&gt;ScrapFly provides &lt;a href="https://scrapfly.io/docs/scrape-api/getting-started" rel="noopener noreferrer"&gt;web scraping&lt;/a&gt;, &lt;a href="https://scrapfly.io/docs/screenshot-api/getting-started" rel="noopener noreferrer"&gt;screenshot&lt;/a&gt;, and &lt;a href="https://scrapfly.io/docs/extraction-api/getting-started" rel="noopener noreferrer"&gt;extraction&lt;/a&gt; APIs for data collection at scale.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/anti-scraping-protection" rel="noopener noreferrer"&gt;Anti-bot protection bypass&lt;/a&gt; - scrape web pages without blocking!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/proxy" rel="noopener noreferrer"&gt;Rotating residential proxies&lt;/a&gt; - prevent IP address and geographic blocks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-rendering" rel="noopener noreferrer"&gt;JavaScript rendering&lt;/a&gt; - scrape dynamic web pages through cloud browsers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-scenario" rel="noopener noreferrer"&gt;Full browser automation&lt;/a&gt; - control browsers to scroll, input and click on objects.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/getting-started#api_param_format" rel="noopener noreferrer"&gt;Format conversion&lt;/a&gt; - scrape as HTML, JSON, Text, or Markdown.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/sdk/python" rel="noopener noreferrer"&gt;Python&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/sdk/typescript" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt; SDKs, as well as &lt;a href="https://scrapfly.io/docs/sdk/scrapy" rel="noopener noreferrer"&gt;Scrapy&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/integration/getting-started" rel="noopener noreferrer"&gt;no-code tool integrations&lt;/a&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" alt="Comprehensive Guide to OkHttp for Java and Kotlin" width="876" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a simple example of how you can use okhttp with Scrapfly's Scraping API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;okhttp3.OkHttpClient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;okhttp3.Request&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;okhttp3.Response&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.IOException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OkHttpExample&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;OkHttpClient&lt;/span&gt; &lt;span class="n"&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;OkHttpClient&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;HttpUrl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt; &lt;span class="n"&gt;urlBuilder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpUrl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://api.scrapfly.io/scrape"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newBuilder&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// Required parameters: your API key and URL to scrape&lt;/span&gt;
        &lt;span class="n"&gt;urlBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addQueryParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"key"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"YOUR_API_KEY"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;urlBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addQueryParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"url"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"https://web-scraping.dev/product/1"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Optional parameters:&lt;/span&gt;
        &lt;span class="c1"&gt;// enable anti scraping protection bypass&lt;/span&gt;
        &lt;span class="n"&gt;urlBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addQueryParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"asp"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// use proxies of a specific countries&lt;/span&gt;
        &lt;span class="n"&gt;urlBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addQueryParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"country"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"US,CA,DE"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// enable headless browser&lt;/span&gt;
        &lt;span class="n"&gt;urlBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addQueryParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"render_js"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// see more on scrapfly docs: https://scrapfly.io/docs/scrape-api/getting-started#spec&lt;/span&gt;

        &lt;span class="c1"&gt;// Building and send request&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urlBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;request&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;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Response&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newCall&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isSuccessful&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Response Body: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;string&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Status Code: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Request Failed: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;To wrap our intro to okhttp let's take a look at some frequently asked questions that we might have missed in our guide:&lt;/p&gt;

&lt;h4&gt;
  
  
  Can OkHttp be used for Crawling?
&lt;/h4&gt;

&lt;p&gt;Yes, OkHttp can be used for web scraping and crawling tasks. It handles multiple concurrent HTTP requests, making it a solid choice for crawlers. However, for specialized crawling purposes, you may want to look into dedicated crawl APIs for better efficiency.&lt;/p&gt;

&lt;h4&gt;
  
  
  Can OkHttp handle large file uploads or downloads?
&lt;/h4&gt;

&lt;p&gt;Yes, OkHttp is capable of handling large file uploads and downloads efficiently. It allows you to stream data via &lt;code&gt;RequestBody&lt;/code&gt; for uploads and &lt;code&gt;ResponseBody&lt;/code&gt; for downloads, ensuring that large files can be processed in chunks without consuming excessive memory. You can implement custom logic to track progress, manage buffers, and avoid memory issues during these operations.&lt;/p&gt;

&lt;h4&gt;
  
  
  Is OkHttp thread-safe?
&lt;/h4&gt;

&lt;p&gt;Yes, OkHttp is designed to be thread-safe. The &lt;code&gt;OkHttpClient&lt;/code&gt; instance itself can be shared across multiple threads, making it ideal for concurrent requests. However, individual &lt;code&gt;Request&lt;/code&gt; and &lt;code&gt;Response&lt;/code&gt; objects are not thread-safe, so they should be used in a single thread or context. To maximize efficiency, it’s recommended to reuse the same &lt;code&gt;OkHttpClient&lt;/code&gt; instance across your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;OkHttp is a versatile and powerful HTTP client that provides developers with the tools they need for smooth, efficient network communication in Java and Android development. Here's a quick recap of the key points we covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supports &lt;strong&gt;HTTP/2&lt;/strong&gt; , &lt;strong&gt;asynchronous requests&lt;/strong&gt; , &lt;strong&gt;interceptors&lt;/strong&gt; , &lt;strong&gt;built-in caching&lt;/strong&gt; , &lt;strong&gt;timeouts&lt;/strong&gt; , and &lt;strong&gt;HTTPS&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Offers features like &lt;strong&gt;compression&lt;/strong&gt; , &lt;strong&gt;redirect handling&lt;/strong&gt; , &lt;strong&gt;WebSocket&lt;/strong&gt; , and &lt;strong&gt;authentication support&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Simple to set up using &lt;strong&gt;Maven&lt;/strong&gt; or &lt;strong&gt;Gradle&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Provides an easy way to handle &lt;strong&gt;GET&lt;/strong&gt; , &lt;strong&gt;POST&lt;/strong&gt; , and other HTTP methods, both synchronously and asynchronously.&lt;/li&gt;
&lt;li&gt;Add &lt;strong&gt;custom headers&lt;/strong&gt; , &lt;strong&gt;cookies&lt;/strong&gt; , and configure &lt;strong&gt;timeouts&lt;/strong&gt; easily.&lt;/li&gt;
&lt;li&gt;Handle advanced cases like &lt;strong&gt;retry logic&lt;/strong&gt; and &lt;strong&gt;HTTPS disabling&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Typical errors include &lt;strong&gt;timeouts&lt;/strong&gt; , &lt;strong&gt;connection issues&lt;/strong&gt; , and &lt;strong&gt;SSL/TLS errors&lt;/strong&gt; , all of which can be managed with proper handling and configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OkHttp is a reliable choice for developers seeking control, efficiency, and a rich set of features for network communication. Its strengths lie in its simplicity combined with the flexibility needed for more advanced use cases.&lt;/p&gt;

</description>
      <category>http</category>
      <category>tools</category>
      <category>java</category>
    </item>
    <item>
      <title>Instant Data Scraper Guide - Web Scraping with No Code</title>
      <dc:creator>Scrapfly</dc:creator>
      <pubDate>Wed, 04 Dec 2024 15:43:44 +0000</pubDate>
      <link>https://dev.to/scrapfly/instant-data-scraper-guide-web-scraping-with-no-code-2bp6</link>
      <guid>https://dev.to/scrapfly/instant-data-scraper-guide-web-scraping-with-no-code-2bp6</guid>
      <description>&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_banner.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_banner.svg" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="1910" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Web scraping has become an essential tool for accessing and organizing data from the web, but coding skills are often seen as a barrier. Thankfully, no-code automation tools allow anyone to collect data effortlessly—without writing any code.&lt;/p&gt;

&lt;p&gt;By leveraging accessible automation tools like &lt;a href="https://www.make.com/" rel="noopener noreferrer"&gt;Zapier&lt;/a&gt; and &lt;a href="https://zapier.com/" rel="noopener noreferrer"&gt;Make.com&lt;/a&gt;, you can automate the scraping process in minutes. In this guide, we'll explore how these no-code solutions can be combined with tools like Google Sheets integrations and browser extensions to make data scraping easy and accessible.&lt;/p&gt;

&lt;p&gt;Whether you're a beginner or just looking for an efficient way to gather web data, this guide will show you how to instantly scrape data without any technical headaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Instant Data Scraping?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Instant Data Scraping&lt;/strong&gt; is a concept that simplifies the process of collecting data from websites by using accessible, no-code tools.&lt;/p&gt;

&lt;p&gt;Instead of traditional coding methods, this approach focuses on leveraging user-friendly interfaces and automated workflows to perform web scraping. Think of it as a combination of tools like Zapier or Make.com that enable you to extract data as effortlessly as setting up a simple workflow.&lt;/p&gt;

&lt;p&gt;With this concept, changes in documents (such as new entries in a Google Sheet or interactions through browser extensions) can trigger data scraping actions.&lt;/p&gt;

&lt;p&gt;This makes data collection as easy as updating a spreadsheet or setting up an automation, allowing anyone to harness the power of web scraping without needing to learn how to code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instant Scraping with Google Sheets
&lt;/h2&gt;

&lt;p&gt;One of the most accessible ways to start instant data scraping is by integrating it with &lt;strong&gt;Google Sheets&lt;/strong&gt;. This method takes advantage of change detection, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding new rows&lt;/li&gt;
&lt;li&gt;Deleting rows&lt;/li&gt;
&lt;li&gt;Updating existing rows&lt;/li&gt;
&lt;li&gt;Creating new sheets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these actions can trigger web scraping actions automatically. Imagine updating a Google Sheet with a website URL and instantly scraping in relevant data without lifting a finger.&lt;/p&gt;

&lt;p&gt;To streamline the scraping and data extraction process, we’ll also be using Scrapfly's no-code integrations.&lt;/p&gt;

&lt;p&gt;ScrapFly provides &lt;a href="https://scrapfly.io/docs/scrape-api/getting-started" rel="noopener noreferrer"&gt;web scraping&lt;/a&gt;, &lt;a href="https://scrapfly.io/docs/screenshot-api/getting-started" rel="noopener noreferrer"&gt;screenshot&lt;/a&gt;, and &lt;a href="https://scrapfly.io/docs/extraction-api/getting-started" rel="noopener noreferrer"&gt;extraction&lt;/a&gt; APIs for data collection at scale.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/anti-scraping-protection" rel="noopener noreferrer"&gt;Anti-bot protection bypass&lt;/a&gt; - scrape web pages without blocking!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/proxy" rel="noopener noreferrer"&gt;Rotating residential proxies&lt;/a&gt; - prevent IP address and geographic blocks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-rendering" rel="noopener noreferrer"&gt;JavaScript rendering&lt;/a&gt; - scrape dynamic web pages through cloud browsers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-scenario" rel="noopener noreferrer"&gt;Full browser automation&lt;/a&gt; - control browsers to scroll, input and click on objects.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/getting-started#api_param_format" rel="noopener noreferrer"&gt;Format conversion&lt;/a&gt; - scrape as HTML, JSON, Text, or Markdown.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/sdk/python" rel="noopener noreferrer"&gt;Python&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/sdk/typescript" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt; SDKs, as well as &lt;a href="https://scrapfly.io/docs/sdk/scrapy" rel="noopener noreferrer"&gt;Scrapy&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/integration/getting-started" rel="noopener noreferrer"&gt;no-code tool integrations&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While Scrapfly's API's require coding knowledge to be used, Scrapfly offers no-code integrations with automation tools like Zapier and Make.com. Those integrations allow everyone to leverage Scrapfly's cutting-edge features through simple and accessible UIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connecting Google Sheets and Scrapfly with Make.com
&lt;/h3&gt;

&lt;p&gt;Make.com is an automation platform that allows users to build complex workflows without writing code. It’s similar to Zapier, but with added flexibility for connecting apps and services in more detailed ways.&lt;/p&gt;

&lt;p&gt;In this guide, we’ll use Make.com to automate the entire scraping process—from detecting changes in Google Sheets to extracting data via Scrapfly.&lt;/p&gt;

&lt;p&gt;Create an new spreadsheet in google sheets. The spreadsheet should have 2 sheets, one to add new URLs to scrape and the other is to store the data extracted from the URLs.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_new-google-sheet.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_new-google-sheet.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a new scenario from you make.com dashboard using the "Create a new scenario button":&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_create-new-scenario.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_create-new-scenario.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="510" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the scenario builder, we will start with the input data node, which is the Google Sheets action &lt;strong&gt;"Watch New Rows"&lt;/strong&gt;. The action will prompt you to connect your google account to get access to the your sheets.&lt;/p&gt;

&lt;p&gt;Once the account is connected, fill the action options as in the image below, note that the &lt;strong&gt;spreadsheet id&lt;/strong&gt; and the &lt;strong&gt;sheet name&lt;/strong&gt; vary according to the sheet you have created on google sheets.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_watch-new-rows-options.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_watch-new-rows-options.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we set all the action options, the action returns a list of new rows every time it runs.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_sheet-action-output.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_sheet-action-output.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The action will automatically have a trigger on it that triggers the action every 15 minutes. Meaning that once we are done with the scenario and it is activated, it will check for new changes in the google sheet every 15 minutes. Feel free to change this time interval to suit your 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_scheduling-options.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_scheduling-options.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="702"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the "Watch New Rows" action returns a &lt;strong&gt;list&lt;/strong&gt; of new rows, we will need to add an &lt;strong&gt;"Iterator"&lt;/strong&gt; node that iterates over this list and allows us to scrape each URL one by one.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_add-iterator.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_add-iterator.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The URLs will be located in column &lt;strong&gt;A&lt;/strong&gt; of the sheet, so will add this column as the iterartor array.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_set-iterator-array-value.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_set-iterator-array-value.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we will use the Scrapfly's "Scrape a webpage" action.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_add-scrapfly-action.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_add-scrapfly-action.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The action will prompt you to connect you Scrapfly account using the API key which you can find a the top of your Scrapfly dashbaord.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_connect-API-key.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_connect-API-key.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The URL value fed to the "Scrape a webpage" action will be the value coming from the "Iterator".&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_connect-URL-value.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_connect-URL-value.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The "Scrape a webpage" action returns a collection with a "Result" object that contains the "Content" of the the scraped webpage.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_scrape-output.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_scrape-output.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now connect the "Scrape a webpage" action to a new "Extract Data" action provided by Scrapfly. This action allows you to extract structured JSON data from unstructured data like HTML, raw text, or markdown using AI.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_add-extract-action.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_add-extract-action.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inside the action options, set the body to the content returned by the scraping action.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_extract-body.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_extract-body.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also set the extraction prompt, which is a simple AI prompt specifying what data you need to be extracted. You can set this prompt to be static for all URLs, but it can also be dynamic and fed from the excel sheet for advanced uses.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_extraction-prompt.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_extraction-prompt.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we have the extracted data, we can transform it into a JSON string using the "Transform to JSON" action.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_transform-to-json.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_transform-to-json.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have the extracted data as a JSON string, we can create a new sheet to store the results (Sheet 2) and send the data to the google sheet using the "Add a Row" Action.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_add-a-row-action.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_add-a-row-action.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="754"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, the scenario is done, activate it from your make.com dashboard and add a new URL to your spreadsheet to see it in the works.&lt;/p&gt;




&lt;p&gt;With this we've made a no code scraper using Google Sheets, Make.com and Scrapfly in just a few minutes! This is a simple example of what you can do with these tools, you can add more complexity to the scenario by adding more actions and conditions to suit your needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scrapfly Screenshot API Action
&lt;/h3&gt;

&lt;p&gt;Scrapfly also offers the "Capture Webpage Screenshot" action on make.com. This action allows you to automate capturing screenshots for any wesbite, which can be used to web testing or price monitoring tools.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_screenshot-action.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_screenshot-action.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In its most basic form, the action expects the website URL for which the screenshot will be captured. You can also provide additional options to the action for more customization, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Screenshot image format (png, jpg, webp...)&lt;/li&gt;
&lt;li&gt;Capture target (full viewport, specific element with CSS selector or XPATH)&lt;/li&gt;
&lt;li&gt;Screen Resolution (1920x1080, 2560x1440...)&lt;/li&gt;
&lt;li&gt;And more&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_screenshot-action-options.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_screenshot-action-options.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="673"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can add this action to scenario we built above and store the image on Google Drive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instant Scraping Inputs
&lt;/h2&gt;

&lt;p&gt;Beyond Google Sheets, there are many other ways to trigger instant data scraping using change detection. The beauty of Instant Data Scraping lies in its flexibility—you can set up automations to kick off data scraping whenever specific changes are detected in a variety of inputs. Here are some examples:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Email Triggers&lt;/strong&gt; : Automatically scrape data when specific types of emails are received, such as notifications or order confirmations.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_email-triggers.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_email-triggers.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="620"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Slack Bots&lt;/strong&gt; : Use a Slack bot to detect messages in a particular channel and trigger a scraping workflow.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_slack-triggers.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_slack-triggers.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="613"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Webhook Triggers&lt;/strong&gt; : Use webhooks to start scraping whenever data is pushed from another service or app.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_webhook-triggers.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_webhook-triggers.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloud File Uploads&lt;/strong&gt; : Detect new file uploads to cloud storage (like Google Drive or Dropbox) and initiate a scraping process to extract data from documents or links.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_drive-triggers.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_drive-triggers.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database Changes&lt;/strong&gt; : Set up triggers based on changes in a database, such as new records being added or existing ones updated.&lt;/p&gt;

&lt;p&gt;With these diverse input options, Instant Data Scraping provides a powerful, adaptable way to gather the information you need—right when you need it. This flexibility makes it ideal for anyone wanting to automate their data collection workflows without spending time on manual processes or coding.&lt;/p&gt;

&lt;h2&gt;
  
  
  On-Demand Scraping
&lt;/h2&gt;

&lt;p&gt;Another powerful feature of Instant Data Scraping is the ability to initiate scraping workflows on demand. This means you can start data collection whenever it suits you, rather than relying solely on change detection triggers. Here are a few options to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google Forms Integration&lt;/strong&gt; : Google Forms can be linked to Google Sheets to easily add new entries that trigger the scraping workflow. For example, users can submit a form with a URL, and that URL is instantly scraped using Scrapfly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zapier Browser Extension&lt;/strong&gt; : Zapier has a &lt;a href="https://zapier.com/l/install-chrome-extension" rel="noopener noreferrer"&gt;browser extension&lt;/a&gt; that allows you to manually trigger actions while browsing. With this, you can scrape data from a web page with a single click, making it convenient for quick, on-the-fly data collection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make.com Mobile App&lt;/strong&gt; : Make.com also has a &lt;a href="https://www.make.com/en/help/tutorials/mobile-app" rel="noopener noreferrer"&gt;mobile app&lt;/a&gt; that allows you to trigger workflows from your phone. This means you can initiate scraping actions from anywhere, making data collection as simple as tapping a button on your device.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These on-demand scraping options provide the flexibility to collect data exactly when you need it. Whether you’re at your desk or on the go, you can always get the data you need instantly and without any coding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scheduled Scraping
&lt;/h2&gt;

&lt;p&gt;While Instant Data Scraping provides excellent flexibility with real-time and on-demand data collection, there are times when scheduling scraping tasks makes more sense.&lt;/p&gt;

&lt;p&gt;Scheduled scraping is perfect for when you need consistent data at regular intervals without having to manually initiate the process. For example, you can set up scraping to happen daily, weekly, or even hourly, depending on your requirements.&lt;/p&gt;

&lt;p&gt;Using tools like Scrapfly, you can easily set up these schedules to ensure your data is always up-to-date. You won't be locked into a single solution either — using platforms like Make.com or Zapier, you can schedule scraping workflows to pull information at your preferred times, giving you the freedom to maintain an automated yet highly controlled data collection process.&lt;/p&gt;

&lt;p&gt;Here an example of how scheduling works in make.com:&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_make.com-scheduling.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-make-instant-data-scraper_make.com-scheduling.webp" alt="Instant Data Scraper Guide - Web Scraping with No Code" width="800" height="634"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This alternative provides a balanced approach for users who require both instant access to data and regular updates, ensuring no opportunity is missed, and data accuracy is always maintained.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;To recap what we covered in this guide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Instant Data Scraping&lt;/strong&gt; : A no-code concept for web scraping using accessible tools like Zapier, Make.com, and Scrapfly, enabling anyone to gather data without coding skills.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What is Instant Data Scraping?&lt;/strong&gt; : Explained how tools like browser extensions and Google Sheet integrations can automate web scraping.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Sheets Integration&lt;/strong&gt; : Demonstrated change detection powered scraping using Google Sheets, Scrapfly, and Make.com for an end-to-end automation workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diverse Inputs for Scraping&lt;/strong&gt; : Explored different trigger inputs, such as email notifications, Slack bots, database changes, webhooks, and cloud file uploads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On-Demand Scraping&lt;/strong&gt; : Showed how scraping can be triggered manually using tools like Google Forms, the Zapier browser extension, or the Make.com mobile app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scheduled Scraping&lt;/strong&gt; : Discussed how scheduled scraping is a viable alternative for consistent data collection, allowing workflows to run automatically at specified intervals.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you need real-time data, scheduled scraping, or on-demand access, Instant Data Scraping gives you multiple flexible options for gathering the data you need—without writing a single line of code.&lt;/p&gt;

</description>
      <category>tools</category>
      <category>scraping</category>
      <category>nocode</category>
    </item>
    <item>
      <title>What is HTTP 499 Status Code and How to Fix it?</title>
      <dc:creator>Scrapfly</dc:creator>
      <pubDate>Fri, 29 Nov 2024 08:21:36 +0000</pubDate>
      <link>https://dev.to/scrapfly/what-is-http-499-status-code-and-how-to-fix-it-2d6g</link>
      <guid>https://dev.to/scrapfly/what-is-http-499-status-code-and-how-to-fix-it-2d6g</guid>
      <description>&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fwhat-is-499-status-code-client-closed-request_banner.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fwhat-is-499-status-code-client-closed-request_banner.svg" alt="What is HTTP 499 Status Code and How to Fix it?" width="1600" height="836"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine this: You’re surfing the web or managing your server when, suddenly, you’re greeted with an error you’ve never encountered before— &lt;strong&gt;499&lt;/strong&gt;. It’s not as famous as the notorious 404 or the dreaded 500, but this cryptic error has been making its way into logs, frustrating developers and users alike.&lt;/p&gt;

&lt;p&gt;So, what exactly is the &lt;strong&gt;499 error&lt;/strong&gt;? Why does it appear, and what can you do to prevent it? In this article, we’ll demystify this client-side HTTP status code, explore its origins, and provide actionable steps to resolve it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the 499 Status Code
&lt;/h2&gt;

&lt;p&gt;To understand the &lt;strong&gt;499 status code&lt;/strong&gt; , we first need to recognize that it doesn’t belong to the standard HTTP status codes outlined by the Internet Engineering Task Force (IETF). Instead, it’s a non-standard, server-specific code introduced by &lt;a href="https://nginx.org/en/index.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Nginx&lt;/strong&gt;&lt;/a&gt;, one of the most popular web servers globally.&lt;/p&gt;

&lt;p&gt;Status code 499, often labeled as &lt;strong&gt;"Client Closed Request"&lt;/strong&gt; , indicates that the client (browser or API consumer) terminated the connection before the server could deliver its response. In simpler terms, the &lt;strong&gt;client grew impatient&lt;/strong&gt; and hung up the call before the server could answer.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why a Non-standard Error?
&lt;/h4&gt;

&lt;p&gt;499 error's association with Nginx stems from the server’s need to log this specific client-side behavior.&lt;/p&gt;

&lt;p&gt;Unlike standard HTTP codes, which aim for universal implementation, the 499 code helps Nginx administrators monitor and debug unique issues caused by &lt;strong&gt;client-side interruptions&lt;/strong&gt; or &lt;strong&gt;network latency&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Understanding its origin highlights an important distinction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The 499 error is not a bug in the server or application but a signal of external factors, such as poor client connectivity or mismatched timeout settings. This makes it an essential tool for diagnosing performance bottlenecks in client-server communication.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By decoding its definition and purpose, we can see how the 499 status code serves as a valuable diagnostic indicator, helping web developers uncover the story behind incomplete requests. But why does it happen, and what does it reveal about the client-server relationship? Let’s explore further.&lt;/p&gt;

&lt;h2&gt;
  
  
  Causes of the 499 Status Code
&lt;/h2&gt;

&lt;p&gt;The 499 status code is a direct result of interruptions in the client-server communication process. Several common scenarios can trigger this error, each shedding light on different aspects of how requests are handled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client-Side Request Cancellations&lt;/strong&gt; : Users may manually stop loading a page or an API consumer may terminate a request prematurely. This abrupt action cuts the connection before the server has a chance to respond, leading to status code 499.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network Instability or Interruptions&lt;/strong&gt; : Unreliable connections, such as weak Wi-Fi or mobile data, can cause requests to drop unexpectedly. The server still processes the request, only to find the client has already disconnected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server-Side Delays Leading to Client Timeouts&lt;/strong&gt; : When a server takes too long to process a request, clients often lose patience. Whether due to large database queries or overloaded servers, these delays can cause the client to close the connection and result in a logged 499 error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client-Side Timeout Configurations&lt;/strong&gt; : Some clients, such as browsers or API integrations, have strict timeout settings. If the server response exceeds these predefined thresholds, the client cancels the request, resulting in a 499 error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Overzealous Proxy or Firewall Rules&lt;/strong&gt; : Intermediate systems like proxies or firewalls can sometimes terminate requests if they detect unusual patterns or if a timeout configuration is too aggressive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Misconfigured APIs or SDKs&lt;/strong&gt; : When third-party APIs or client-side SDKs are not configured properly, they may inadvertently close connections too soon, especially in high-latency environments.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding these causes is crucial because it highlights the shared responsibility between clients and servers in maintaining seamless communication. Identifying the root cause helps determine whether the solution lies in optimizing client behavior, improving server performance, or addressing network issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Impact on Web Scraping and Automation
&lt;/h2&gt;

&lt;p&gt;For those relying on web scraping or automated workflows, encountering 499 errors can present significant challenges. These errors interrupt the seamless flow of data extraction, making it difficult to retrieve the information needed efficiently. When clients terminate requests prematurely, the scraper may fail to capture complete responses, leading to incomplete datasets or broken scripts.&lt;/p&gt;

&lt;p&gt;In automated workflows, where tasks are chained and dependent on accurate data retrieval, a 499 error can disrupt the entire process. For example, a timeout in one step of the workflow might cascade into downstream failures, wasting time and resources.&lt;/p&gt;

&lt;p&gt;Addressing these issues often requires robust error-handling mechanisms and timeout configurations. Ensuring that automated tools can retry failed requests or gracefully handle incomplete responses is essential to maintaining reliability in scraping and workflow automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strategies to Mitigate 499 Errors
&lt;/h2&gt;

&lt;p&gt;To minimize the occurrence of 499 errors, it’s essential to adopt proactive strategies that enhance the resilience of client-server interactions. Here are key approaches:&lt;/p&gt;

&lt;h3&gt;
  
  
  Retry Mechanisms with Exponential Backoff
&lt;/h3&gt;

&lt;p&gt;When a request fails due to a 499 error, using a retry mechanism with exponential backoff can prevent repeated abrupt failures. This approach delays successive retries by increasing intervals, reducing the likelihood of overwhelming the server.&lt;/p&gt;

&lt;p&gt;Here are some examples on how to implement exponential backoff retries in Python and Javascript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_with_retries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_retries&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_retries&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;499&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestException&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;pass&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchWithRetries&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="nx"&gt;maxRetries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Start with 1 second&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;attempt&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;attempt&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;maxRetries&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;attempt&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="k"&gt;try&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;response&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;fetch&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AbortSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;499&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Attempt &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; failed`&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&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;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="nx"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mi"&gt;2&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="kc"&gt;null&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;h3&gt;
  
  
  Client-Side Timeout Settings
&lt;/h3&gt;

&lt;p&gt;Timeout settings play a critical role in reducing 499 errors. Misconfigured timeout values can cause clients to terminate requests prematurely, especially for long-running processes. Below are examples of configuring timeouts in common HTTP client libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Timeout set to 30 seconds
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.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="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AbortSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// Timeout set to 30 seconds&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;axios&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.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="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30000&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// Timeout set to 30 seconds&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;response&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="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Stable Network Connections
&lt;/h3&gt;

&lt;p&gt;A stable and reliable network connection is crucial for avoiding interruptions. Consider the following practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use wired connections over wireless for critical tasks.&lt;/li&gt;
&lt;li&gt;Implement redundancy in network infrastructure, such as failover mechanisms.&lt;/li&gt;
&lt;li&gt;Monitor connection health and latency in real time to preempt issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By integrating these strategies, you can significantly reduce the frequency of 499 errors, ensuring smoother communication and more reliable workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for HTTP Clients and Web Scrapers
&lt;/h2&gt;

&lt;p&gt;When building reliable HTTP clients or web scrapers, following best practices can significantly reduce the impact of errors like 499. Below are actionable steps to improve resilience and efficiency:&lt;/p&gt;

&lt;h3&gt;
  
  
  Monitoring and Logging
&lt;/h3&gt;

&lt;p&gt;Accurate monitoring and logging help identify patterns and frequency of 499 errors, enabling you to address their root causes effectively. We will demostrate how to effectively log errors like the http status code 499 error in Python and Javascript.&lt;/p&gt;

&lt;p&gt;For Python we will be using the &lt;code&gt;logging&lt;/code&gt; module which is built-in in the Python standard library. While for Javascript, we will be using a popular third party library for logging called &lt;a href="https://github.com/winstonjs/winston" rel="noopener noreferrer"&gt;Winston&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="c1"&gt;# Configure logging
&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;errors.log&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%(asctime)s - %(levelname)s - %(message)s&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;499&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;logging&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;499 error encountered for URL: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestException&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Request failed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="c1"&gt;# Example usage
&lt;/span&gt;&lt;span class="nf"&gt;fetch_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;winston&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;winston&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Configure winston logging&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;winston&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createLogger&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;winston&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;winston&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nx"&gt;winston&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;timestamp&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;level&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;message&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="na"&gt;transports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;winston&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;errors.log&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchUrl&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="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&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;response&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;fetch&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;499&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`499 error encountered for URL: &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;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Request failed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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;// Example usage&lt;/span&gt;
&lt;span class="nf"&gt;fetchUrl&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://example.com&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;h3&gt;
  
  
  Robust Error-Handling
&lt;/h3&gt;

&lt;p&gt;Implement error-handling mechanisms that not only retry failed requests but also log and categorize errors for debugging. This ensures that transient issues like 499 errors are managed without affecting the overall workflow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wrap network requests in &lt;code&gt;try-catch&lt;/code&gt; blocks or similar structures to gracefully handle exceptions.&lt;/li&gt;
&lt;li&gt;Use exponential backoff strategies, as demonstrated earlier, for retries to prevent overwhelming the server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ethical Scraping Practices
&lt;/h3&gt;

&lt;p&gt;Ethical scraping practices reduce the chances of overloading servers and triggering client-side terminations like 499 errors. These include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rate Limiting&lt;/strong&gt; : Avoid making too many requests in a short time. Use libraries like &lt;code&gt;time.sleep&lt;/code&gt; in Python or &lt;code&gt;setTimeout&lt;/code&gt; in JavaScript to introduce delays.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Respecting Robots.txt&lt;/strong&gt; : Check the site’s &lt;code&gt;robots.txt&lt;/code&gt; file to understand which resources are allowed to be scraped.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Agent Rotation&lt;/strong&gt; : Use a pool of user agents to mimic legitimate traffic patterns while scraping.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Incorporating these practices ensures smoother scraping operations and fosters a responsible approach to web automation. By monitoring 499 errors and adopting robust handling routines, you can create resilient, efficient systems while respecting the servers you interact with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Power Up with Scrapfly
&lt;/h2&gt;

&lt;p&gt;ScrapFly provides &lt;a href="https://scrapfly.io/docs/scrape-api/getting-started" rel="noopener noreferrer"&gt;web scraping&lt;/a&gt;, &lt;a href="https://scrapfly.io/docs/screenshot-api/getting-started" rel="noopener noreferrer"&gt;screenshot&lt;/a&gt;, and &lt;a href="https://scrapfly.io/docs/extraction-api/getting-started" rel="noopener noreferrer"&gt;extraction&lt;/a&gt; APIs for data collection at scale.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/anti-scraping-protection" rel="noopener noreferrer"&gt;Anti-bot protection bypass&lt;/a&gt; - scrape web pages without blocking!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/proxy" rel="noopener noreferrer"&gt;Rotating residential proxies&lt;/a&gt; - prevent IP address and geographic blocks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-rendering" rel="noopener noreferrer"&gt;JavaScript rendering&lt;/a&gt; - scrape dynamic web pages through cloud browsers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-scenario" rel="noopener noreferrer"&gt;Full browser automation&lt;/a&gt; - control browsers to scroll, input and click on objects.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/getting-started#api_param_format" rel="noopener noreferrer"&gt;Format conversion&lt;/a&gt; - scrape as HTML, JSON, Text, or Markdown.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/sdk/python" rel="noopener noreferrer"&gt;Python&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/sdk/typescript" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt; SDKs, as well as &lt;a href="https://scrapfly.io/docs/sdk/scrapy" rel="noopener noreferrer"&gt;Scrapy&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/integration/getting-started" rel="noopener noreferrer"&gt;no-code tool integrations&lt;/a&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" alt="What is HTTP 499 Status Code and How to Fix it?" width="876" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The 499 status code, though non-standard, plays a significant role in diagnosing issues in client-server communication, particularly in Nginx environments. It arises primarily from client-side interruptions, unstable networks, or server delays. This makes it a unique but essential tool for debugging and performance monitoring.&lt;/p&gt;

&lt;p&gt;By understanding the causes and adopting best practices, developers and web scrapers can handle 499 errors effectively, ensuring seamless communication between clients and servers while maintaining ethical and efficient operations.&lt;/p&gt;

</description>
      <category>http</category>
      <category>nginx</category>
    </item>
    <item>
      <title>How to Use cURL to Download Files?</title>
      <dc:creator>Scrapfly</dc:creator>
      <pubDate>Mon, 25 Nov 2024 09:51:46 +0000</pubDate>
      <link>https://dev.to/scrapfly/how-to-use-curl-to-download-files-2ioe</link>
      <guid>https://dev.to/scrapfly/how-to-use-curl-to-download-files-2ioe</guid>
      <description>&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-curl-download-file_banner.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fhow-to-curl-download-file_banner.svg" alt="How to Use cURL to Download Files" width="1275" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://curl.se/" rel="noopener noreferrer"&gt;Curl&lt;/a&gt;, short for "Client URL," is a versatile command-line tool used for transferring data with URLs. It's widely favored by developers and system administrators for its ability to interact with a multitude of protocols such as HTTP, HTTPS, FTP, and more.&lt;/p&gt;

&lt;p&gt;Using curl to download files simplifies the process by enabling direct command-line interaction with web resources. Curl is not only efficient and lightweight — operating without the need for a graphical interface — but also cross-platform, working seamlessly on Linux, macOS, and Windows systems.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore how to use curl to download a file from the web, covering various use cases and demonstrating the tool's versatility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Curl to Download Files?
&lt;/h2&gt;

&lt;p&gt;Curl stands out as an exceptional file downloading tool, offering a robust set of features that make it indispensable for developers. Here's what makes curl particularly powerful for downloading files:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-Protocol Support&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handles various protocols like HTTP, HTTPS, FTP, and SFTP.&lt;/li&gt;
&lt;li&gt;Eliminates the need for multiple tools when working with different protocols.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Resume Interrupted Downloads&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the &lt;code&gt;-C -&lt;/code&gt; option to continue downloads from where they left off.&lt;/li&gt;
&lt;li&gt;Saves time and bandwidth by avoiding the need to restart downloads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bandwidth Management&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limit download speeds using &lt;code&gt;--limit-rate&lt;/code&gt; to manage bandwidth usage.&lt;/li&gt;
&lt;li&gt;Prevents downloads from consuming all available network resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Proxy Support&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easily configure proxies using options like &lt;code&gt;-x&lt;/code&gt; or &lt;code&gt;--proxy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Supports various proxy types, including HTTP, HTTPS, SOCKS4, and SOCKS5.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Authentication Handling&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supports a range of authentication methods, including Basic, Digest, NTLM, and OAuth.&lt;/li&gt;
&lt;li&gt;Access protected resources seamlessly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Secure Transfers&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supports SSL/TLS protocols for secure file transfers.&lt;/li&gt;
&lt;li&gt;Verify SSL certificates and use secure authentication methods.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cross-Platform Compatibility&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Available on Linux, macOS, Windows, and more.&lt;/li&gt;
&lt;li&gt;Consistent functionality across different operating systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Automation and Scripting&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easily integrates into scripts for automated tasks.&lt;/li&gt;
&lt;li&gt;Ideal for scheduled downloads using cron jobs or Windows Task Scheduler.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Curl's robust feature set makes it an excellent choice for downloading files, whether you're handling simple tasks or complex download operations. Its flexibility and efficiency empower users to manage downloads effectively in various environments.&lt;/p&gt;

&lt;p&gt;You can learn more about curl and its options in our article about &lt;a href="https://scrapfly.io/blog/how-to-use-curl-for-web-scraping" rel="noopener noreferrer"&gt;using curl for web-scraping&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's explore the basic usage of curl for downloading files and then dive deeper into more complex and unconventional scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Curl Basic File Download Options
&lt;/h2&gt;

&lt;p&gt;By default, when curl is run on a file URL without any extra options, the file content is displayed is the terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://web-scraping.dev/assets/pdf/tos.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, you can use curl to save to file with its original name using the &lt;code&gt;-O&lt;/code&gt; (uppercase "O" for Output) option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; https://web-scraping.dev/assets/pdf/tos.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command saves the file as &lt;code&gt;tos.pdf&lt;/code&gt;, retaining the original filename.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom File Name on Download
&lt;/h3&gt;

&lt;p&gt;To save the downloaded file with a custom name, use the &lt;code&gt;-o&lt;/code&gt; (lowercase "o") option followed by the desired filename:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;filename] &lt;span class="o"&gt;[&lt;/span&gt;URL]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; web-scraping-tos.pdf https://web-scraping.dev/assets/pdf/tos.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command downloads &lt;code&gt;tos.pdf&lt;/code&gt; and saves it as &lt;code&gt;web-scraping-tos.pdf&lt;/code&gt; on your local machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Show Progress Bar / Download Silently
&lt;/h3&gt;

&lt;p&gt;Curl show a progress meter by default. However, you can suppress the progress meter and show a simple progress bar instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Show Progress Bar&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Replace the default progress meter with a simple progress bar using &lt;code&gt;--progress-bar&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="nt"&gt;--progress-bar&lt;/span&gt; https://web-scraping.dev/assets/pdf/tos.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Download Silently&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To suppress all output, including progress and error messages, use the &lt;code&gt;-s&lt;/code&gt; or &lt;code&gt;--silent&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; https://web-scraping.dev/assets/pdf/tos.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Silent Mode with Error Messages&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want to hide the progress meter but still see error messages, combine &lt;code&gt;-s&lt;/code&gt; with &lt;code&gt;-S&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-S&lt;/span&gt; https://web-scraping.dev/assets/pdf/tos.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Retry for Unstable Connections
&lt;/h3&gt;

&lt;p&gt;For unreliable network connections, you can configure curl to retry downloads automatically:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Set Number of Retries&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use the &lt;code&gt;--retry&lt;/code&gt; option followed by the number of retry attempts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="nt"&gt;--retry&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;number] &lt;span class="o"&gt;[&lt;/span&gt;URL]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="nt"&gt;--retry&lt;/span&gt; 5 https://web-scraping.dev/assets/pdf/tos.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command retries the download up to 5 times upon failure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Specify Retry Delay&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To add a delay between retries, use &lt;code&gt;--retry-delay&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="nt"&gt;--retry&lt;/span&gt; 5 &lt;span class="nt"&gt;--retry-delay&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;seconds] &lt;span class="o"&gt;[&lt;/span&gt;URL]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="nt"&gt;--retry&lt;/span&gt; 5 &lt;span class="nt"&gt;--retry-delay&lt;/span&gt; 10 https://web-scraping.dev/assets/pdf/tos.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This adds a 10-second pause between each retry attempt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retry on All Errors&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By default, curl retries on transient errors. To make it retry on all errors, use &lt;code&gt;--retry-all-errors&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="nt"&gt;--retry&lt;/span&gt; 5 &lt;span class="nt"&gt;--retry-all-errors&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;URL]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="nt"&gt;--retry&lt;/span&gt; 5 &lt;span class="nt"&gt;--retry-all-errors&lt;/span&gt; https://web-scraping.dev/assets/pdf/tos.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Handling Large File Downloads
&lt;/h2&gt;

&lt;p&gt;Downloading large files can pose challenges such as network congestion or impacting other users on the same network. Curl offers options to manage these issues effectively.&lt;/p&gt;

&lt;p&gt;To prevent a large download from consuming all your available bandwidth, you can limit the download speed using the &lt;code&gt;--limit-rate&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="nt"&gt;--limit-rate&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;speed] &lt;span class="o"&gt;[&lt;/span&gt;URL]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="nt"&gt;--limit-rate&lt;/span&gt; 500k https://web-scraping.dev/assets/pdf/tos.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command limits the download speed to 500 kilobytes per second. You can specify the speed using suffixes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;k&lt;/strong&gt; or &lt;strong&gt;K&lt;/strong&gt; for kilobytes (e.g., &lt;code&gt;500k&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;m&lt;/strong&gt; or &lt;strong&gt;M&lt;/strong&gt; for megabytes (e.g., &lt;code&gt;2M&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bandwidth Management&lt;/strong&gt; : Ensures other network activities aren't slowed down.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Stability&lt;/strong&gt; : Reduces the risk of connection drops due to high bandwidth usage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Insecure Downloading
&lt;/h2&gt;

&lt;p&gt;In some cases, you might need to use cURL to download a file from a server with an invalid or self-signed SSL certificate. Curl verifies SSL certificates by default, which can block these downloads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disable SSL Certificate Verification&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; Disabling SSL verification can expose you to security risks like man-in-the-middle attacks. Use this option only when you're certain about the server's trustworthiness.&lt;/p&gt;

&lt;p&gt;To bypass SSL certificate checks, use the &lt;code&gt;-k&lt;/code&gt; or &lt;code&gt;--insecure&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="nt"&gt;-k&lt;/span&gt; https://web-scraping.dev/assets/pdf/tos.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command tells curl to ignore SSL certificate validation and proceed with the download.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verifying File Integrity
&lt;/h2&gt;

&lt;p&gt;Ensuring that a downloaded file hasn't been tampered with is crucial, especially for important or large files. You can verify file integrity using checksum tools like &lt;code&gt;sha256sum&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using &lt;code&gt;sha256sum&lt;/code&gt; to Verify Downloads&lt;/strong&gt;&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Download the File and Its Checksum&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; https://example.com/file.zip
curl &lt;span class="nt"&gt;-O&lt;/span&gt; https://example.com/file.zip.sha256
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Verify the Checksum&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sha256sum&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; file.zip.sha256
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;-c&lt;/code&gt; option tells &lt;code&gt;sha256sum&lt;/code&gt; to check the file against the provided checksum.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Manual Verification:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the checksum isn't provided in a file:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Get the Expected Checksum&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Obtain the checksum value from the website or provider.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Calculate the Downloaded File's Checksum&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sha256sum &lt;/span&gt;file.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;This command outputs a checksum that you can compare with the expected value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 file.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt; : Confirms the file hasn't been altered maliciously.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Integrity&lt;/strong&gt; : Ensures the file isn't corrupted due to network issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Handling Authentication
&lt;/h2&gt;

&lt;p&gt;When downloading files from protected resources, authentication is often required. Curl supports various authentication methods to access these resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authorization Header&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To include an authorization token or API key in your request, use the &lt;code&gt;-H&lt;/code&gt; option to add a custom header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer your_token_here"&lt;/span&gt; https://api.example.com/securefile.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example uses bearer token authentication, but you can use any other authentication method supported by curl.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cookie Session&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If authentication relies on session cookies, you can manage cookies using curl:&lt;/p&gt;

&lt;p&gt;When logging in, save the session cookies to a file using the &lt;code&gt;-c&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-c&lt;/span&gt; cookies.txt &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"username=user&amp;amp;password=pass"&lt;/span&gt; https://example.com/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;-d&lt;/code&gt; option sends POST data for login credentials.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cookies received during login are saved to &lt;code&gt;cookies.txt&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Saved Cookies&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use the saved cookies for subsequent requests with the &lt;code&gt;-b&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; cookies.txt https://example.com/securefile.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Session Management&lt;/strong&gt; : Maintains login sessions across multiple requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Workflows&lt;/strong&gt; : Scripts can handle login and file download processes seamlessly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Utilizing these options enhances the reliability of your file downloads, ensuring efficiency, security, and smoother operations even with unstable internet connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Curl Command Builder
&lt;/h2&gt;

&lt;p&gt;To simplify the process of creating cURL commands for file downloads, we've created a curl command builder tool. This interactive form allows you to select various options and generate the corresponding curl command instantly:&lt;/p&gt;

&lt;p&gt;Check it out &lt;a href="https://scrapfly.io/blog/how-to-curl-download-file/#curl-command-builder" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;br&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%2Fhm5xnpzetnf70byjcfmm.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%2Fhm5xnpzetnf70byjcfmm.png" alt="Image description" width="800" height="551"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Automating Curl Downloads with Crontab
&lt;/h2&gt;

&lt;p&gt;Automating file downloads ensures you always have the latest data without manual effort. By integrating &lt;code&gt;curl&lt;/code&gt; with &lt;code&gt;crontab&lt;/code&gt;, you can schedule downloads to run at specified times, enhancing efficiency and productivity.&lt;/p&gt;
&lt;h4&gt;
  
  
  What Is Crontab?
&lt;/h4&gt;

&lt;p&gt;Crontab is a time-based job scheduler in Unix-like operating systems. It allows users to schedule scripts or commands to run automatically at predefined times or intervals.&lt;/p&gt;
&lt;h4&gt;
  
  
  Steps to Automate Downloads Using Crontab
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. Create a Download Script (Optional)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Write the Script&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a shell script (e.g., &lt;code&gt;download.sh&lt;/code&gt;) that contains your &lt;code&gt;curl&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Navigate to the desired directory&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/download/directory

&lt;span class="c"&gt;# Download the file using curl&lt;/span&gt;
curl &lt;span class="nt"&gt;-O&lt;/span&gt; https://example.com/file.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Make the Script Executable&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /path/to/download.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Edit the Crontab File&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open Crontab Editor&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;crontab &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add a New Cron Job&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Insert a line following the cron syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /path/to/command
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example: Schedule the Script to Run Daily at 2 AM&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;0 2 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /path/to/download.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fields Explained:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Minute:&lt;/strong&gt; &lt;code&gt;0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hour:&lt;/strong&gt; &lt;code&gt;2&lt;/code&gt; (2 AM)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Day of Month:&lt;/strong&gt; &lt;code&gt;*&lt;/code&gt; (Every day)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Month:&lt;/strong&gt; &lt;code&gt;*&lt;/code&gt; (Every month)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Day of Week:&lt;/strong&gt; &lt;code&gt;*&lt;/code&gt; (Every day of the week)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Save and Exit&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
After adding your cron job, save the file. The cron service will automatically pick up the new schedule.&lt;/p&gt;

&lt;p&gt;Automating &lt;code&gt;curl&lt;/code&gt; downloads with crontab streamlines your workflow, ensuring timely and consistent data retrieval. Whether you're updating datasets, synchronizing files, or performing regular backups, this combination offers a robust solution for scheduled tasks.&lt;/p&gt;
&lt;h2&gt;
  
  
  Bypassing Download Blocks
&lt;/h2&gt;

&lt;p&gt;When attempting to use curl to download files, you might encounter situations where the download is blocked or fails. This can be due to various reasons such as network restrictions, server configurations, or security measures that prevent automated requests.&lt;/p&gt;

&lt;p&gt;The most common reason for download blocks is that the server is blocking automated requests. To bypass this, you can add a custom browser user-agent string to your request headers to mimic a real browser request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="s2"&gt;"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"&lt;/span&gt; https://example.com/file.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example uses the &lt;code&gt;-A&lt;/code&gt; option to set a custom user-agent string. You can replace the string with any other user-agent string that mimics a real browser request.&lt;/p&gt;

&lt;p&gt;Changing the user-agent string is the most basic method to bypass download blocks. However, some servers are sophisticated enough to still block requests with custom user-agent strings. In these cases, you may need to use a more advanced tools like curl-impersonate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lwthiker/curl-impersonate" rel="noopener noreferrer"&gt;Curl-impersonate&lt;/a&gt; is a modified version of cURL that simulates the TLS fingerprint of major web browsers, like Chrome, Firefox, Edge and Safari, by mimicing their TLS and HTTP2 configuration. It also overrides the default cURL headers, such as the User-Agent, with regular header values. This makes the cURL Impersonate requests look like those sent from the browsers, preventing the firewalls from detecting the usage of HTTP clients.&lt;/p&gt;

&lt;p&gt;You can learn more about curl-impersonate in our dedicated guide on &lt;a href="https://scrapfly.io/blog/curl-impersonate-scrape-chrome-firefox-tls-http2-fingerprint" rel="noopener noreferrer"&gt;using curl-impersonate for web-scraping&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Power Up File Downloads with Scrapfly
&lt;/h2&gt;

&lt;p&gt;Downloading files programmatically can quickly become a cumbersome task. Especially when the files are protected against automation and bots using sophisticated bot protection systems that cannot be bypassed with tools like &lt;code&gt;curl-impersonate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Scrapfly has millions of proxies and connection fingerprints that can be used to bypass protection against automated traffic and significantly simplify your file download process.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" alt="How to Use cURL to Download Files" width="876" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ScrapFly provides &lt;a href="https://scrapfly.io/docs/scrape-api/getting-started" rel="noopener noreferrer"&gt;web scraping&lt;/a&gt;, &lt;a href="https://scrapfly.io/docs/screenshot-api/getting-started" rel="noopener noreferrer"&gt;screenshot&lt;/a&gt;, and &lt;a href="https://scrapfly.io/docs/extraction-api/getting-started" rel="noopener noreferrer"&gt;extraction&lt;/a&gt; APIs for data collection at scale.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/anti-scraping-protection" rel="noopener noreferrer"&gt;Anti-bot protection bypass&lt;/a&gt; - scrape web pages without blocking!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/proxy" rel="noopener noreferrer"&gt;Rotating residential proxies&lt;/a&gt; - prevent IP address and geographic blocks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-rendering" rel="noopener noreferrer"&gt;JavaScript rendering&lt;/a&gt; - scrape dynamic web pages through cloud browsers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-scenario" rel="noopener noreferrer"&gt;Full browser automation&lt;/a&gt; - control browsers to scroll, input and click on objects.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/getting-started#api_param_format" rel="noopener noreferrer"&gt;Format conversion&lt;/a&gt; - scrape as HTML, JSON, Text, or Markdown.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/sdk/python" rel="noopener noreferrer"&gt;Python&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/sdk/typescript" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt; SDKs, as well as &lt;a href="https://scrapfly.io/docs/sdk/scrapy" rel="noopener noreferrer"&gt;Scrapy&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/integration/getting-started" rel="noopener noreferrer"&gt;no-code tool integrations&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, here is how to use Scrapfly's web scraping API to download a file, we will use Scrapfly's Pyhton SDK to call the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;scrapfly&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ScrapflyClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ScrapeConfig&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;

&lt;span class="n"&gt;scrapfly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ScrapflyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR SCRAPFLY KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;FILE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://web-scraping.dev/assets/pdf/tos.pdf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scrapfly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scrape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;ScrapeConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;FILE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;asp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&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;## decode base64 file data
&lt;/span&gt;&lt;span class="n"&gt;file_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tos.pdf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scrapfly's API automatically detects that the requested URL is a file and return the binary content of the file encoded with base64. Which is why we decoded the content returned by the API before we saved it to a file called &lt;code&gt;tos.pdf&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;Wrapping up, here are some common questions concering downlaoding files with curl:&lt;/p&gt;

&lt;h4&gt;
  
  
  Can I resume an interrupted download with &lt;code&gt;curl&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;Yes, you can resume an interrupted download by using the appropriate option in &lt;code&gt;curl&lt;/code&gt; that allows you to continue from where the download stopped, which is especially useful for large files or unstable connections.&lt;/p&gt;

&lt;h4&gt;
  
  
  Is wget a better alternative to curl for downloading files?
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;wget&lt;/code&gt; is another command-line tool specifically designed for downloading files. While &lt;code&gt;curl&lt;/code&gt; is versatile and supports various protocols and features, &lt;code&gt;wget&lt;/code&gt; is often preferred for its simplicity in handling recursive downloads and its ability to download entire websites. You can learn more about the differenced between curl and wget in our dedicated &lt;a href="https://scrapfly.io/blog/curl-vs-wget/" rel="noopener noreferrer"&gt;curl vs wget article&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  How do I download multiple files at once using &lt;code&gt;curl&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;You can download multiple files simultaneously by specifying multiple URLs in a single command or by using scripting methods to loop through a list of URLs, allowing for efficient batch downloads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Curl is a versatile tool when it comes to downloading files, offering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Protocol Support&lt;/strong&gt; : Works with HTTP, HTTPS, FTP, and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resume Capability&lt;/strong&gt; : Restarts interrupted downloads with ease.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proxy and Bandwidth Management&lt;/strong&gt; : Supports proxies and limits download speed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication Support&lt;/strong&gt; : Handles cookies, tokens, and secured resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation&lt;/strong&gt; : Integrates with scripts and scheduling tools like crontab.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For advanced needs, tools like curl-impersonate or services like Scrapfly can bypass sophisticated bot protections, offering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Bypass Capabilities&lt;/strong&gt; : Overcomes anti-bot systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Flexibility&lt;/strong&gt; : Simplifies complex file downloads with robust solutions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Curl’s feature-set make it essential for managing simple to complex downloads efficiently.&lt;/p&gt;

</description>
      <category>curl</category>
      <category>tools</category>
    </item>
    <item>
      <title>What is Error 1015 (Cloudflare) and How to Fix it?</title>
      <dc:creator>Scrapfly</dc:creator>
      <pubDate>Wed, 20 Nov 2024 08:28:50 +0000</pubDate>
      <link>https://dev.to/scrapfly/what-is-error-1015-cloudflare-and-how-to-fix-it-46cl</link>
      <guid>https://dev.to/scrapfly/what-is-error-1015-cloudflare-and-how-to-fix-it-46cl</guid>
      <description>&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fwhat-is-cloudflare-1015-error-and-how-to-fix-it_banner.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fwhat-is-cloudflare-1015-error-and-how-to-fix-it_banner.svg" alt="What is Error 1015 (Cloudflare) and How to Fix it?" width="1600" height="836"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Encountering Cloudflare Error 1015 can be frustrating, especially when you're trying to access important content or services online. This error indicates that you've been rate-limited, but what does that mean, and how can you fix it?&lt;/p&gt;

&lt;p&gt;In this article, we'll explore the causes of Error 1015 and provide practical solutions to mitigate it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Error 1015?
&lt;/h2&gt;

&lt;p&gt;Cloudflare Error 1015, commonly displayed as _ &lt;strong&gt;"You are being rate limited"&lt;/strong&gt; _, occurs when a user exceeds the number of requests allowed by a website within a specific time frame.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_cloudflare-1015.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_cloudflare-1015.webp" alt="What is Error 1015 (Cloudflare) and How to Fix it?" width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The error can include one of the following messages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"error 1015 rate limited"&lt;/li&gt;
&lt;li&gt;"service resource is being rate limited"&lt;/li&gt;
&lt;li&gt;"error 1015 you are being rate limited"&lt;/li&gt;
&lt;li&gt;or simply "this resource is being rate limited"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these messages relate to the same error 1015 error just different in presentation.&lt;/p&gt;

&lt;p&gt;This rate-limiting is a protective mechanism to safeguard websites from malicious activities such as Distributed Denial of Service (DDoS) attacks, brute-force login attempts, or web scraping bots.&lt;/p&gt;

&lt;p&gt;Some reasons that trigger a Cloudflare 1015 error include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Excessive Requests&lt;/strong&gt; : Making too many requests in a short period, intentionally or unintentionally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Scripts or Bots&lt;/strong&gt; : Using automated tools that send multiple requests rapidly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared Networks&lt;/strong&gt; : Being on a network (like a corporate or school network) where multiple users access the same service simultaneously.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where is Error 1015 Encountered?
&lt;/h2&gt;

&lt;p&gt;Since error 1015 "rate limited" is Cloudflare specific, it's only encountered if a website uses &lt;a href="https://developers.cloudflare.com/waf/" rel="noopener noreferrer"&gt;Cloudflare Web Application Firewall (WAF)&lt;/a&gt; or &lt;a href="https://developers.cloudflare.com/bots/" rel="noopener noreferrer"&gt;Cloudflare's anti-bot services&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloudflare Web Application Firewall (WAF)
&lt;/h3&gt;

&lt;p&gt;Cloudflare &lt;strong&gt;WAF&lt;/strong&gt; acts as a shield between your website and the internet. It monitors and filters incoming traffic based on predefined security rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Functions of WAF:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blocks Malicious Traffic:&lt;/strong&gt; Filters out attacks like SQL injection, cross-site scripting (XSS), and other web exploits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable Rules:&lt;/strong&gt; Allows website owners to set specific rules tailored to their application's needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-Time Monitoring:&lt;/strong&gt; Provides insights into the nature of threats and traffic patterns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;WAF blocks malicious traffic by returning a 1015 Error page to the client indicating they are being rate-limited.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloudflare Anti-Bot System
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Anti-Bot&lt;/strong&gt; system is designed to detect and mitigate automated bot traffic that could be harmful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features of Anti-Bot System:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Behavioral Analysis:&lt;/strong&gt; Monitors user behavior to distinguish between humans and bots.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Challenge Mechanisms:&lt;/strong&gt; Implements CAPTCHA or JavaScript challenges to verify users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Machine Learning:&lt;/strong&gt; Utilizes algorithms to adapt to new bot behaviors over time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cloudflare Anti-Bot System treats bot traffic as malicious traffic, even if the bot is not spamming the website, so just the detection of a client as being automated is enough to result in a 1015 error.&lt;/p&gt;

&lt;p&gt;If you are trying to scrape a website with Cloudflare anti-bot protection, check out our &lt;a href="https://scrapfly.io/blog/how-to-bypass-cloudflare-anti-scraping/" rel="noopener noreferrer"&gt;Cloudflare bypass guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mitigating error 1015
&lt;/h2&gt;

&lt;p&gt;As already mentioned, 1015 error is either an indication of being &lt;strong&gt;rate-limited&lt;/strong&gt; or being detected as &lt;strong&gt;automated traffic&lt;/strong&gt; (bot). Each cause has its own means of mitigation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rate Limiting
&lt;/h3&gt;

&lt;p&gt;Rate limiting controls the number of requests a user can make to a server within a set time frame. Understanding how rate limiting works can help you adjust your behavior to avoid triggering it.&lt;/p&gt;

&lt;p&gt;Common Axes Used for Rate Limiting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IP Address&lt;/strong&gt; : Limits based on the user's internet protocol address.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User-Agent Header&lt;/strong&gt; : Identifies the application, operating system, vendor, and version of the requesting user agent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cookies and Session Identifiers&lt;/strong&gt; : Tracks user sessions to enforce limits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript Fingerprinting&lt;/strong&gt; : Uses browser characteristics (like screen resolution, installed plugins) to create a unique user profile. You can learn more about JS fingerprinting through our &lt;a href="https://scrapfly.io/blog/browser-fingerprinting-with-creepjs/" rel="noopener noreferrer"&gt;CreepJS fingerprinting guide&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To avoid getting rate-limited, you can either &lt;a href="https://scrapfly.io/blog/how-to-rate-limit-asynchronous-python-requests/" rel="noopener noreferrer"&gt;&lt;strong&gt;reduce request frequency&lt;/strong&gt;&lt;/a&gt; by spacing out your requests to the server or use &lt;strong&gt;proxies&lt;/strong&gt; to distribute the workload over multiple IP addresses. We explain proxies in depth in our &lt;a href="https://scrapfly.io/blog/introduction-to-proxies-in-web-scraping/" rel="noopener noreferrer"&gt;Complete Guide To Using Proxies For Web Scraping&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Bot Detection
&lt;/h3&gt;

&lt;p&gt;Most websites have robust bot protection measures in place to prevent web scraping and automated traffic. When bot traffic is detected, websites usually throw a &lt;a href="https://scrapfly.io/blog/what-is-status-code-403-forbidden-how-to-fix-it/" rel="noopener noreferrer"&gt;403 error&lt;/a&gt; or &lt;a href="https://scrapfly.io/blog/what-is-http-error-429-too-many-requests/" rel="noopener noreferrer"&gt;429 error&lt;/a&gt;, and in Cloudflare's case, the HTML shows a 1015 "You are being rate limited" error.&lt;/p&gt;

&lt;p&gt;In this case, the bot would be rate-limited but with no plan from the server to remove that limit, meaning it is permanently blocked.&lt;/p&gt;

&lt;p&gt;Bot detection is usually achieved using complex fingerprinting techniques that find loopholes in requests to leak their automated nature. There are many tools that block those leaks and help bypass fingerprint detection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/lexiforest/curl_cffi" rel="noopener noreferrer"&gt;&lt;strong&gt;curl_cffi&lt;/strong&gt;&lt;/a&gt;: a Python HTTP client library built on top of &lt;a href="https://github.com/lwthiker/curl-impersonate" rel="noopener noreferrer"&gt;curl-impersonate&lt;/a&gt;. It modifies the request configuration to mimic normal browsers, which helps bypass bot detection. You can learn more about curl_cffi in our &lt;a href="https://scrapfly.io/blog/curl-impersonate-scrape-chrome-firefox-tls-http2-fingerprint/#curl-impersonate-with-python" rel="noopener noreferrer"&gt;curl impersonate guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/ultrafunkamsterdam/undetected-chromedriver" rel="noopener noreferrer"&gt;&lt;strong&gt;undetected-chromedriver&lt;/strong&gt;&lt;/a&gt;: a modified selenium webdriver that has built-in measures to combat websites that block automated headless browsers scraping their pages. Get to know more about it in our in-depth guide on &lt;a href="https://scrapfly.io/blog/web-scraping-without-blocking-using-undetected-chromedriver/" rel="noopener noreferrer"&gt;web scraping with undetected chromedriver&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Error 1015 Popular Examples
&lt;/h2&gt;

&lt;p&gt;Many popular websites use Cloudflare's services under the hood, giving them the ability to rate-limit users when suspicious traffic is detected. Let's look at some common scenarios where you can get 1015 error on popular websites:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Discord&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario:&lt;/strong&gt; Rapidly sending messages or joining/leaving servers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Slow down activities and avoid using bots that automate actions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Crunchyroll&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario:&lt;/strong&gt; Refreshing pages excessively or using downloaders to save content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Use the service as intended and consider subscribing for offline access.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario:&lt;/strong&gt; Making too many API requests in a short time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Implement rate-limiting in your application and monitor your usage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Red Robin&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario:&lt;/strong&gt; Placing multiple orders rapidly or refreshing the menu pages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Complete one order before starting another and minimize page refreshes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;USTravelDocs&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario:&lt;/strong&gt; Constantly checking for visa appointment availability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Limit checks to a reasonable frequency and avoid using automation tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Chess.com&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario:&lt;/strong&gt; Rapidly starting and ending games or refreshing leaderboards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Engage in games at a normal pace and avoid unnecessary page reloads.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Power Up with Scrapfly
&lt;/h2&gt;

&lt;p&gt;Bypassing Cloudflare's Error 1015 while possible is very difficult - let Scrapfly do it for you!&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" alt="What is Error 1015 (Cloudflare) and How to Fix it?" width="876" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ScrapFly provides &lt;a href="https://scrapfly.io/docs/scrape-api/getting-started" rel="noopener noreferrer"&gt;web scraping&lt;/a&gt;, &lt;a href="https://scrapfly.io/docs/screenshot-api/getting-started" rel="noopener noreferrer"&gt;screenshot&lt;/a&gt;, and &lt;a href="https://scrapfly.io/docs/extraction-api/getting-started" rel="noopener noreferrer"&gt;extraction&lt;/a&gt; APIs for data collection at scale. Each product is equipped with an automatic bypass for any anti-bot system and we achieve this by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintaining a fleet of real, reinforced web browsers with real fingerprint profiles.&lt;/li&gt;
&lt;li&gt;Millions of self-healing proxies of the highest possible trust score.&lt;/li&gt;
&lt;li&gt;Constantly evolving and adapting to new anti-bot systems.&lt;/li&gt;
&lt;li&gt;We've been doing this publicly since 2020 with the best bypass on the market!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It takes Scrapfly several full-time engineers to maintain this system, so you don't have to!&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;Wrapping up, here are some common questions about Cloudflare's 1015 error.&lt;/p&gt;

&lt;h4&gt;
  
  
  How long does Error 1015 last?
&lt;/h4&gt;

&lt;p&gt;The duration can vary based on the website's settings. It can range from a few minutes to several hours. It's best to wait and try again later.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why am I getting Error 1015 when I haven't done anything unusual?
&lt;/h4&gt;

&lt;p&gt;Factors like shared IP addresses, background applications making requests, or malware can cause unexpected rate limits. Check your system for any unwanted activity.&lt;/p&gt;

&lt;h4&gt;
  
  
  Can Error 1015 mean I am permanently blocked?
&lt;/h4&gt;

&lt;p&gt;While Cloudflare Error 1015 typically indicates a temporary rate limit due to excessive requests within a short period, under certain circumstances, it can signify a more prolonged or even permanent block due to repeated violations or suspicious activity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Cloudflare Error 1015 serves as a protective measure for websites against excessive or malicious requests. Understanding the reasons behind this error helps users adjust their online activities to prevent future occurrences.&lt;/p&gt;

&lt;p&gt;Whether you are being rate limited for frequently requesting a website or you are permanently blocked due to bot detection, Scrapfly's powerful proxy pools and anti-scraping protection measures can help you bypass this error.&lt;/p&gt;

</description>
      <category>scraperblocking</category>
      <category>http</category>
    </item>
    <item>
      <title>What HTTP Error 412 Precondition Failed and How to Fix it?</title>
      <dc:creator>Scrapfly</dc:creator>
      <pubDate>Fri, 15 Nov 2024 05:40:04 +0000</pubDate>
      <link>https://dev.to/scrapfly/what-http-error-412-precondition-failed-and-how-to-fix-it-3njh</link>
      <guid>https://dev.to/scrapfly/what-http-error-412-precondition-failed-and-how-to-fix-it-3njh</guid>
      <description>&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fwhat-is-http-412-error-precondition-failed_banner.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fwhat-is-http-412-error-precondition-failed_banner.svg" alt="What HTTP Error 412 Precondition Failed and How to Fix it?" width="1600" height="836"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Encountering an HTTP 412 error can be perplexing, especially when you're unsure why it happened. This article sheds light on what the HTTP 412 error means, explores its common causes, and discusses whether it can indicate blocking.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is HTTP 412 Error?
&lt;/h2&gt;

&lt;p&gt;The HTTP 412 error, known as "Precondition Failed," is a client error response status code. It signifies that the server cannot fulfill one or more conditions specified in the request's headers.&lt;/p&gt;

&lt;p&gt;Conditions are typically specified in the request's headers using &lt;strong&gt;conditional headers&lt;/strong&gt; where the header name typically follows the format &lt;code&gt;If-X&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Common conditional headers include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;If-Match&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;If-None-Match&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;If-Modified-Since&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;If-Unmodified-Since&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's take a look at each of these http 412 error causes next in greater detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are HTTP 412 Error causes?
&lt;/h2&gt;

&lt;p&gt;The HTTP 412 "Precondition Failed" error arises when the conditions specified in the client's conditional headers are not met by the server. So, what are these conditions?&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Conditional Headers
&lt;/h3&gt;

&lt;p&gt;Conditional headers help manage resource versions and ensure data integrity during client-server interactions. These headers are often used for caching and concurrency control — like multiple clients working on the same resource.&lt;/p&gt;

&lt;p&gt;Understanding these headers is essential to grasp why a 412 error might occur. Here's the breakdown of each:&lt;/p&gt;

&lt;h4&gt;
  
  
  If-Match
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;If-Match&lt;/code&gt; header makes the request conditional on the client's provided ETag matching the server's current ETag for the resource. An ETag (Entity Tag) is a unique identifier representing a specific version of a resource, like version of HTML page or a file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;How It Works&lt;/strong&gt; : When a client includes an &lt;code&gt;If-Match&lt;/code&gt; header with an ETag value, the server compares this ETag with the current ETag of the requested resource. If they match, the server processes the request. If not, it responds with a 412 error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt; : This is commonly used when updating a resource (&lt;code&gt;PUT&lt;/code&gt; or &lt;code&gt;PATCH&lt;/code&gt; requests) to ensure that the resource hasn't changed since the client last retrieved it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  If-None-Match
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;If-None-Match&lt;/code&gt; header is essentially the opposite of &lt;code&gt;If-Match&lt;/code&gt;. It makes the request conditional on the resource's ETag not matching any of the ETags provided in the header.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;How It Works&lt;/strong&gt; : The server checks if the resource's current ETag matches any of the ETags listed. If there's a match, and the request method is &lt;code&gt;GET&lt;/code&gt; or &lt;code&gt;HEAD&lt;/code&gt;, the server responds with a &lt;code&gt;304 Not Modified&lt;/code&gt;. For other methods, it returns a 412 error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt; : This header is used to fetch a resource only if it has changed, optimizing network usage by reducing unnecessary data transfer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  If-Modified-Since
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;If-Modified-Since&lt;/code&gt; header makes the request conditional on the resource having been modified after the specified date.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;How It Works&lt;/strong&gt; : If the resource hasn't been modified since the given date, the server responds with a &lt;code&gt;304 Not Modified&lt;/code&gt;. If it has been modified, the server processes the request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt; : Useful for caching mechanisms, where the client can avoid downloading unchanged resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  If-Unmodified-Since
&lt;/h4&gt;

&lt;p&gt;This header is used to ensure that the resource hasn't changed since a specific date.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;How It Works&lt;/strong&gt; : If the resource has been modified after the date provided, the server returns a 412 error. If not, it processes the request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt; : Often used when deleting or updating resources to prevent conflicts due to concurrent modifications.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Common Causes of 412 HTTP code
&lt;/h3&gt;

&lt;h4&gt;
  
  
  ETag or Modification Date Mismatch
&lt;/h4&gt;

&lt;p&gt;A primary cause is when the ETag or the modification date provided by the client doesn't match the server's current value. This mismatch indicates that the resource has changed since the client last accessed it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario&lt;/strong&gt; : A client attempts to update a resource using an &lt;code&gt;If-Match&lt;/code&gt; header with an outdated ETag. Since the resource has been modified by another client or process, the ETags don't match, resulting in a 412 error.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Concurrent Resource Modifications
&lt;/h4&gt;

&lt;p&gt;In environments where multiple clients can modify resources, a 412 error helps prevent conflicting updates.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario&lt;/strong&gt; : Two clients attempt to update the same resource simultaneously. The first update succeeds, altering the resource's ETag. When the second client sends its update with the old ETag in the &lt;code&gt;If-Match&lt;/code&gt; header, the server rejects it with a 412 error.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Avoiding HTTP 412 Errors
&lt;/h3&gt;

&lt;p&gt;To prevent encountering a 412 error:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ensure Synchronization&lt;/strong&gt; : Keep client-side caches and system clocks synchronized with the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handle ETags Properly&lt;/strong&gt; : Always update stored ETags after a successful resource retrieval or modification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement Conditional Headers Correctly&lt;/strong&gt; : Understand the semantics of each header and use them appropriately in your requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manage Concurrent Access&lt;/strong&gt; : In applications where multiple clients access the same resources, implement proper version control or locking mechanisms.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By carefully managing conditional requests and maintaining up-to-date information about server resources, clients can minimize the chances of triggering a 412 Precondition Failed error.&lt;/p&gt;

&lt;h2&gt;
  
  
  412 HTTP Code in Web Scraping?
&lt;/h2&gt;

&lt;p&gt;HTTP Status 412 is usually encountered when using condtional headers with &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;PUT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt; requests. For example, when updating a resource concurrently with another user or a resource that is cached on the client and not updated. Such scenarios are very rare in web scraping.&lt;/p&gt;

&lt;p&gt;If you encounter it when make a &lt;code&gt;GET&lt;/code&gt; request or any request where conditional header are not used, it could mean that the error is returned delibirately by the server to block web scraping and deceive the scraper in thinking there's a technical issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Power Up with Scrapfly
&lt;/h2&gt;

&lt;p&gt;ScrapFly provides &lt;a href="https://scrapfly.io/docs/scrape-api/getting-started" rel="noopener noreferrer"&gt;web scraping&lt;/a&gt;, &lt;a href="https://scrapfly.io/docs/screenshot-api/getting-started" rel="noopener noreferrer"&gt;screenshot&lt;/a&gt;, and &lt;a href="https://scrapfly.io/docs/extraction-api/getting-started" rel="noopener noreferrer"&gt;extraction&lt;/a&gt; APIs for data collection at scale.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/anti-scraping-protection" rel="noopener noreferrer"&gt;Anti-bot protection bypass&lt;/a&gt; - scrape web pages without blocking!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/proxy" rel="noopener noreferrer"&gt;Rotating residential proxies&lt;/a&gt; - prevent IP address and geographic blocks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-rendering" rel="noopener noreferrer"&gt;JavaScript rendering&lt;/a&gt; - scrape dynamic web pages through cloud browsers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-scenario" rel="noopener noreferrer"&gt;Full browser automation&lt;/a&gt; - control browsers to scroll, input and click on objects.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/getting-started#api_param_format" rel="noopener noreferrer"&gt;Format conversion&lt;/a&gt; - scrape as HTML, JSON, Text, or Markdown.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/sdk/python" rel="noopener noreferrer"&gt;Python&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/sdk/typescript" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt; SDKs, as well as &lt;a href="https://scrapfly.io/docs/sdk/scrapy" rel="noopener noreferrer"&gt;Scrapy&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/integration/getting-started" rel="noopener noreferrer"&gt;no-code tool integrations&lt;/a&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" alt="What HTTP Error 412 Precondition Failed and How to Fix it?" width="876" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It takes Scrapfly several full-time engineers to maintain this system, so you don't have to!&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The HTTP 412 error indicates that the server couldn't meet the conditions specified in your request headers. Understanding this error involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recognizing the role of conditional headers.&lt;/li&gt;
&lt;li&gt;Identifying mismatches between client requests and server resources.&lt;/li&gt;
&lt;li&gt;Acknowledging that while it can rarely resemble blocking, it's not its primary purpose.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By grasping the nuances of the HTTP 412 error, you can better troubleshoot and ensure smoother interactions between your client and the server.&lt;/p&gt;

</description>
      <category>api</category>
      <category>http</category>
    </item>
    <item>
      <title>How to Use Yelp API to Extract Business and Review Data</title>
      <dc:creator>Scrapfly</dc:creator>
      <pubDate>Thu, 07 Nov 2024 15:48:07 +0000</pubDate>
      <link>https://dev.to/scrapfly/how-to-use-yelp-api-to-extract-business-and-review-data-3gn1</link>
      <guid>https://dev.to/scrapfly/how-to-use-yelp-api-to-extract-business-and-review-data-3gn1</guid>
      <description>&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fguide-to-yelp-api_banner.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fguide-to-yelp-api_banner.svg" alt="How to Use Yelp API to Extract Business and Review Data" width="3023" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Considered one of the most popular domains for business directories in the US, Yelp contains valuable company details, including addresses, emails, phone numbers, and reviews. But what's the most efficient way to extract these data?&lt;/p&gt;

&lt;p&gt;In this guide, we'll take an extensive look into Yelp API, its key features, pricing, and limitations. Furthermore, we'll discuss potential alternatives. Let's dig in!&lt;/p&gt;

&lt;h4&gt;
  
  
  Legal Disclaimer and Precautions
&lt;/h4&gt;

&lt;p&gt;This tutorial covers popular web scraping techniques for education. Interacting with public servers requires diligence and respect and here's a good summary of what not to do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do not scrape at rates that could damage the website.&lt;/li&gt;
&lt;li&gt;Do not scrape data that's not available publicly.&lt;/li&gt;
&lt;li&gt;Do not store PII of EU citizens who are protected by GDPR.&lt;/li&gt;
&lt;li&gt;Do not repurpose the &lt;em&gt;entire&lt;/em&gt; public datasets which can be illegal in some countries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scrapfly does not offer legal advice but these are good general rules to follow in web scraping&lt;br&gt;&lt;br&gt;
and for more you should consult a lawyer.&lt;/p&gt;
&lt;h2&gt;
  
  
  Yelp API Overview
&lt;/h2&gt;

&lt;p&gt;The Yelp API is a product provided by Yelp for developers to automate certain actions or extract specific business data. Yelp APIs come with different endpoints, covering a wide range of workflows and resources.&lt;/p&gt;

&lt;p&gt;In terms of data extraction, the Yelp API offers the following popular features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search for businesses based on terms, location, categories, or phone numbers.&lt;/li&gt;
&lt;li&gt;Search for business service offerings.&lt;/li&gt;
&lt;li&gt;Search for businesses with food delivery services.&lt;/li&gt;
&lt;li&gt;Retrieve businesses' engagement metrics and review data.&lt;/li&gt;
&lt;li&gt;Retrieve a business's details based on its ID or alias.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that the Yelp API capabilities aren't limited to the above features. Refer to the official &lt;a href="https://docs.developer.yelp.com/reference" rel="noopener noreferrer"&gt;Yelp API documentation&lt;/a&gt; for more.&lt;/p&gt;
&lt;h4&gt;
  
  
  Yelp Fusion API
&lt;/h4&gt;

&lt;p&gt;Yelp includes thousands of business details and millions of equivalent reviews across different sectors and indentures. This makes the queries required to find specific businesses quite complex. Therefore, Yelp has introduced the Fusion API.&lt;/p&gt;

&lt;p&gt;The Fusion API provides an easier business search experience to &lt;strong&gt;find the best matching results powered by an AI chat interface&lt;/strong&gt;. It answers prompted queries and categorizes them into business questions or search results. Then, it retrieves the relevant results with related information, reviews, photos, and more.&lt;/p&gt;

&lt;p&gt;For further details on Yelp Fusion API, refer to the &lt;a href="https://docs.developer.yelp.com/docs/fusion-intro" rel="noopener noreferrer"&gt;official introductory tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Use Yelp API?
&lt;/h3&gt;

&lt;p&gt;Yelp has information and review data for millions of businesses across various sectors and industries. Extracting this data using Yelp empowers different use cases, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Market Research&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Navigating business services on Yelp allows business owners to evaluate their offerings based on the current market trend, which supports decision-making and helps businesses remain competitive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lead Generation&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Considered one of the largest business directories in the US, Yelp API enables easy retrieval of contact information. Details like names, addresses, phone numbers, and emails make building outreach and marketing campaigns easier.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sentiment Analysis&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Using third-party tools and software has made it much easier to utilize LLMs for &lt;a href="https://scrapfly.io/blog/how-to-use-web-scaping-for-rag-applications/" rel="noopener noreferrer"&gt;RAG applications&lt;/a&gt; and &lt;a href="https://scrapfly.io/blog/intro-to-using-web-scraping-for-sentiment-analysis/" rel="noopener noreferrer"&gt;sentiment analysis&lt;/a&gt; models. Hence, extracting data from Yelp reviews is an excellent way to train these language models for context-aware applications.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For further details, have a look at our introduction to &lt;a href="https://scrapfly.io/use-case" rel="noopener noreferrer"&gt;web scraping use cases&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to Use Yelp API?
&lt;/h2&gt;

&lt;p&gt;In the following sections, we'll explore using the Yelp API for data extraction. We'll cover each related resource endpoint and the core parameters.&lt;/p&gt;
&lt;h3&gt;
  
  
  Search for Businesses
&lt;/h3&gt;

&lt;p&gt;One of the most popular Yelp API endpoints is used to search for businesses. The generic search endpoint retrieves basic business data based on the provided search query. Below is the search API endpoint schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--request&lt;/span&gt; GET &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s1"&gt;'https://api.yelp.com/v3/businesses/search?sort_by=best_match&amp;amp;limit=20'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization:Yelp API key'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'accept: application/json'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The business search endpoint accepts different URl parameters to refine and narrow down the retrieved results. Below are the most common query parameters:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;term&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Search term to use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sort_by&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Sorting algoirthm to use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;categories&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;[]string&lt;/td&gt;
&lt;td&gt;Categories to filter search results by&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;location&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Geographic area to filter search results by&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;latitude&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;number&lt;/td&gt;
&lt;td&gt;Latitude of the location to search from&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;longitude&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;number&lt;/td&gt;
&lt;td&gt;Longitude of the location to search from&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;price&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;[]integer&lt;/td&gt;
&lt;td&gt;Pricing levels to filter the search result with&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;attributes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;[]string&lt;/td&gt;
&lt;td&gt;Bussiness attributes to filter by&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;limit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;Number of results to retrieve&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;offset&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;Pagination cursor to start from&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Above, are the commonly used query parameters when searching for businesses. Below is an example of the business details retrieved.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"businesses"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"alias"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"golden-boy-pizza-hamburg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"categories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"alias"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pizza"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Pizza"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"alias"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"food"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Food"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"coordinates"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"latitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;41.7873382568359&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"longitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-123.051551818848&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"display_phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(415) 982-9738"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"distance"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4992.437696561071&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"QPOI0dYeAl3U8iPM_IYWnA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"image_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://yelp-photos.yelpcorp.com/bphoto/b0mx7p6x9Z1ivb8yzaU3dg/o.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"is_closed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"address1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"James"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"address2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Street"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"address3"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"68M"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Los Angeles"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"US"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"display_address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"James"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Street"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"68M"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Los Angeles, CA 22399"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"zip_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"22399"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Golden Boy Pizza"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+14159829738"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"review_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;903&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"transactions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"restaurant_reservation"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.yelp.com/biz/golden-boy-pizza-hamburg?adjust_creative=XsIsNkqpLmHqfJ51zfRn3A&amp;amp;utm_campaign=yelp_api_v3&amp;amp;utm_medium=api_v3_business_search&amp;amp;utm_source=XsIsNkqpLmHqfJ51zfRn3A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"business_hours"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"open"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"is_overnight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;130&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"is_overnight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;630&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1730&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"is_overnight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"hours_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REGULAR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"is_open_now"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"region"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"center"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"latitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;37.76089938976322&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"longitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-122.43644714355469&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6800&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each request to the Yelp API for business search retrieves the matching businesses, with a maximum of 240 entities in each call. However, the results don't include business reviews.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieve Business Data
&lt;/h3&gt;

&lt;p&gt;The business details endpoint retrieves the detailed business content. It follows the below schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--request&lt;/span&gt; GET &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--url&lt;/span&gt; https://api.yelp.com/v3/businesses/business_id_or_alias &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Your Yelp API key'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'accept: application/json'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To retrieve a specific business details, this API endpoint accepts either the business ID or its alias as the &lt;code&gt;business_id_or_alias&lt;/code&gt; path parameter.&lt;/p&gt;

&lt;p&gt;As for the endpoint query parameters, they are limited to the below properties:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;locale&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Locale code in the langauge and country code foramt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;device_platform&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;The platform to use for the &lt;code&gt;mobile_link&lt;/code&gt; property&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here's a sample output of details retrieved by the business API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"alias"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"golden-boy-pizza-hamburg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"categories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"alias"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pizza"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Pizza"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"alias"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"food"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Food"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"coordinates"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"latitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;41.7873382568359&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"longitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-123.051551818848&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"display_phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(415) 982-9738"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"distance"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4992.437696561071&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"QPOI0dYeAl3U8iPM_IYWnA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"image_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://yelp-photos.yelpcorp.com/bphoto/b0mx7p6x9Z1ivb8yzaU3dg/o.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"is_claimed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"is_closed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"date_opened"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"date_closed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"address1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"James"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"address2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Street"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"address3"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"68M"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Los Angeles"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"US"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"display_address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"James"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Street"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"68M"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Los Angeles, CA 22399"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"zip_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"22399"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Golden Boy Pizza"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+14159829738"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"photos"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://s3-media2.fl.yelpcdn.com/bphoto/CPc91bGzKBe95aM5edjhhQ/o.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://s3-media4.fl.yelpcdn.com/bphoto/FmXn6cYO1Mm03UNO5cbOqw/o.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://s3-media4.fl.yelpcdn.com/bphoto/HZVDyYaghwPl2kVbvHuHjA/o.jpg"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"photo_details"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"photo_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CPc91bGzKBe95aM5edjhhQ"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://s3-media2.fl.yelpcdn.com/bphoto/CPc91bGzKBe95aM5edjhhQ/o.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"caption"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Meat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"710,"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"47,"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"is_user_submitted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"false,"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"null,"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"food"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"photo_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FmXn6cYO1Mm03UNO5cbOqw"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://s3-media4.fl.yelpcdn.com/bphoto/FmXn6cYO1Mm03UNO5cbOqw/o.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"caption"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dessert"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;585&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;78&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"is_user_submitted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"null,"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"food"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"photo_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HZVDyYaghwPl2kVbvHuHjA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://s3-media4.fl.yelpcdn.com/bphoto/HZVDyYaghwPl2kVbvHuHjA/o.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"caption"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dessert_2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;710&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;53&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"is_user_submitted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"food"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"photo_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"review_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;903&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hours"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"open"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"is_overnight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;130&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"is_overnight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;630&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1730&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"is_overnight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hours_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REGULAR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"is_open_now"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"special_hours"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2019-02-07"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"is_closed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"is_overnight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1600"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"transactions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"restaurant_reservation"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.yelp.com/biz/golden-boy-pizza-hamburg?adjust_creative=XsIsNkqpLmHqfJ51zfRn3A&amp;amp;utm_campaign=yelp_api_v3&amp;amp;utm_medium=api_v3_business_search&amp;amp;utm_source=XsIsNkqpLmHqfJ51zfRn3A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"attributes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"business_temp_closed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1657868400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outdoor_seating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"liked_by_vegans"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"liked_by_vegetarians"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hot_and_new"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2022-12-10"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"messaging"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.yelp.com/raq/AA5cAADa-F9f5DPqZ-PADA?adjust_creative=5374ujususZtKiSNEg7uhg&amp;amp;utm_campaign=yelp_api_v3&amp;amp;utm_medium=api_v3_graphql&amp;amp;utm_source=5374upadasZtCvMLBg7uhg#popup%3Araq"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"use_case_text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Request a Quote"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"response_rate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"response_time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;791&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"is_enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"yelp_menu_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.yelp.com/menu/golden-boy-pizza-hamburg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rapc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"is_enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"is_eligible"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Despite having the full business details retrieved by this Yelp API endpoint, &lt;strong&gt;the review data aren't included&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieve Service Offerings
&lt;/h3&gt;

&lt;p&gt;We have explored the endpoints responsible for retrieving business details. However, the services provided are retrieved through a dedicated endpoint for service offerings.&lt;/p&gt;

&lt;p&gt;Below is the service offerings API endpoint schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--request&lt;/span&gt; GET &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--url&lt;/span&gt; https://api.yelp.com/v3/businesses/business_id_or_alias/service_offerings &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Your Yelp API key'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'accept: application/json'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above Yelp API endpoint requires a &lt;code&gt;business_id_or_alias&lt;/code&gt; path parameter to identify the related business.&lt;/p&gt;

&lt;p&gt;The related query parameters are used to define localization settings:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;locale&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Locale code in the langauge and country code foramt&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here's an example of what the service offering results look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"bathtub_shower_installation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"drain_repair"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"emergency_services"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"garbage_disposal_repair"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"gas_line_services"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"offers_electric_water_heater_installation"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"eligible"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"backflow_services"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"bathtub_shower_installation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"bathtub_shower_repair"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"drain_installation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"drain_repair"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"emergency_services"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Retrieve Business Reviews
&lt;/h3&gt;

&lt;p&gt;The business review data is among the most frequently requested information on Yelp. For this, Yelp provides a dedicated review API endpoint with the below schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--request&lt;/span&gt; GET &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s1"&gt;'https://api.yelp.com/v3/businesses/business_id_or_alias/reviews?limit=20&amp;amp;sort_by=yelp_sort'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Your Yelp API key'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'accept: application/json'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar to the previous business-related API endpoints, passing the business ID or its alias as a &lt;code&gt;business_id_or_alias&lt;/code&gt; path parameter is required to identify the business entity for retrieving reviews.&lt;/p&gt;

&lt;p&gt;The Yelp review API provides a few query parameters for locality settings and pagination:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;locale&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Locale code in the langauge and country code foramt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;offset&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;Pagination cursor to start from&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;limit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;Number of results to retrieve&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sort_by&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Sorting algoirthm to use&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The review snippet results include details about the review text, rating, and user details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"possible_languages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reviews"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"xAG4O7l-t1ubbwVAlPnDKg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.yelp.com/biz/la-palma-mexicatessen-san-francisco?hrid=hp8hAJ-AnlpqxCCu7kyCWA&amp;amp;adjust_creative=0sidDfoTIHle5vvHEBvF0w&amp;amp;utm_campaign=yelp_api_v3&amp;amp;utm_medium=api_v3_business_reviews&amp;amp;utm_source=0sidDfoTIHle5vvHEBvF0w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Went back again to this place since the last time i visited the bay area 5 months ago, and nothing has changed. Still the sketchy Mission, Still the cashier..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"time_created"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2016-08-29 00:41:13"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"W8UK02IDdRS2GL_66fuq6w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"profile_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.yelp.com/user_details?userid=W8UK02IDdRS2GL_66fuq6w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"image_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://s3-media3.fl.yelpcdn.com/photo/iwoAD12zkONZxJ94ChAaMg/o.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ella A."&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;....&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above example response includes complete review data for each snippet. However, &lt;strong&gt;each review API call limits the number of reviews retrieved to only three&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Yelp API Evaluation
&lt;/h2&gt;

&lt;p&gt;So far, we've explored the technical aspects of the Yelp API. However, a common question arises: is using the Yelp API suitable for extracting business and review data? For this, we must explore two crucial factors: pricing and limitations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Yelp offers different subscription tiers, each varying in pricing and the data fields that can be retrieved. Let's consider the minimum plans required to retrieve both basic business and review data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Business&lt;/strong&gt; data: Starter plan, with pricing of &lt;strong&gt;$7.99 /1,000 API calls&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review&lt;/strong&gt; data: Plus plan, with pricing of &lt;strong&gt;$9.99 /1,000 API calls&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To better explore this, let's evaluate the cost of extracting 1000 business and review data using Yelp API.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Data&lt;/th&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Pricing per 1,000 calls&lt;/th&gt;
&lt;th&gt;Max results per API call&lt;/th&gt;
&lt;th&gt;Cost per 10,000 results&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Business&lt;/td&gt;
&lt;td&gt;Starter&lt;/td&gt;
&lt;td&gt;$7.99&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$79.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reviews&lt;/td&gt;
&lt;td&gt;Plus&lt;/td&gt;
&lt;td&gt;$9.99&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;$33.33&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Above is a rough estimation of the Yelp API costs for extracting 10,000 business and review entities. However, the &lt;strong&gt;subscription plans considered for this cost estimation only cover very basic attributes&lt;/strong&gt;. The full data attributes are only available under the enterprise plan, which &lt;strong&gt;comes at a much higher cost of $14.99 per 1,000 API calls&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For further details on Yelp API pricing, refer to the &lt;a href="https://docs.developer.yelp.com/page/start-your-free-trial" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations
&lt;/h3&gt;

&lt;p&gt;So far, we have explored the available Yelp APIs for business and reviewed data extraction, including their specifications and result schema. However, we have identified the below limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subscription plans are expensive and allow for a limited number of API calls.&lt;/li&gt;
&lt;li&gt;Full data attributes are only accessible through the enterprise plan, which is even more expensive.&lt;/li&gt;
&lt;li&gt;Gathering complete business information requires requesting data from multiple API endpoints.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Yelp API Alternatives: Web Scraping
&lt;/h2&gt;

&lt;p&gt;An alternative to using Yelp API for data extraction is using &lt;strong&gt;web scraping&lt;/strong&gt;. This approach enables extracting data from Yelp's public web pages. Instead of requesting the API endpoints for direct JSON data retrieval, we can &lt;strong&gt;parse the HTML or replicate background API calls&lt;/strong&gt; to extract what we are looking for!&lt;/p&gt;

&lt;p&gt;For example, let's replicate and parse Yelp's public search pages as an alternative to the paid search API endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;parsel&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Selector&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;urllib.parse&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;urlencode&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AsyncClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;

&lt;span class="c1"&gt;# initialize an async httpx client
&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AsyncClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;# enable http2
&lt;/span&gt;    &lt;span class="n"&gt;http2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# add basic browser like headers to prevent getting blocked
&lt;/span&gt;    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Accept-Language&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;en-US,en;q=0.9&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User-Agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Accept&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Accept-Encoding&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gzip, deflate, br&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cookie&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;intl_splash=false&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;follow_redirects&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;parse listing data from the search XHR data&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Request is blocked, use ScrapFly to bypass Yelp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s blocking&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;search_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;selector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;//script[@data-id=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;react-root-props&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;]/text()&lt;/span&gt;&lt;span class="sh"&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="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;react_root_props = &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;rsplit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;legacyProps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;searchAppProps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;searchPageProps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mainContentComponentsListProps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="c1"&gt;# filter search data cards
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bizId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;search_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# filter the max results count
&lt;/span&gt;        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;totalResults&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;props&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="n"&gt;total_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;props&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;totalResults&lt;/span&gt;&lt;span class="sh"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;search_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;total_results&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;scrape_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;scrape single page of yelp search&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_search_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;base_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.yelp.com/search?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;find_desc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;find_loc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;start&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;base_url&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;urlencode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# final url example:
&lt;/span&gt;        &lt;span class="c1"&gt;# https://www.yelp.com/search?find_desc=plumbers&amp;amp;find_loc=Seattle%2C+WA&amp;amp;start=1
&lt;/span&gt;
    &lt;span class="n"&gt;first_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&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="nf"&gt;make_search_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;search_data&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;scrape_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plumbers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Seattle, WA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ensure_ascii&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; __main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;asyncio&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="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we request Yelp search pages given a search term and location. Then, we extract all business results from the page hidden web data. Here are what the results look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"total_results"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"search_data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"bizId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_Wv9uLrzQ1dZ6fgMYjgygg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"searchResultBusiness"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"ranking"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"isAd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"renderAdInfo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Rooter-Man"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"alternateNames"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"businessUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/adredir?ad_business_id=_Wv9uLrzQ1dZ6fgMYjgygg&amp;amp;campaign_id=jpQhVJGCG8ILi71Et0XDdQ&amp;amp;click_origin=search_results&amp;amp;placement=vertical_0&amp;amp;placement_slot=1&amp;amp;redirect_url=https%3A%2F%2Fwww.yelp.com%2Fbiz%2Frooter-man-orting%3Foverride_cta%3DGet%2Bpricing%2B%2526%2Bavailability&amp;amp;request_id=9d07f67caab0b9cc&amp;amp;signature=919646537897431750a9ec41b1240262d0e8596eed098a3d2776e9c9afe1898f&amp;amp;slot=0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"categories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Plumbing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/search?find_desc=Plumbing&amp;amp;find_loc=Seattle%2C+WA"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"priceRange"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"isClickableReview"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"reviewCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"formattedAddress"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"neighborhoods"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"serviceArea"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"parentBusiness"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"servicePricing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"bizSiteUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://biz.yelp.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"serviceOfferings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"businessAttributes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"licenses"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"license_number"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ROOTE**792MT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"license_expiration_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-08-12"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"license_verification_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://secure.lni.wa.gov/verify/Detail.aspx?UBI=602584774&amp;amp;LIC=ROOTE**792MT&amp;amp;SAW="&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"license_verification_status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"verified"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"license_verification_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2023-11-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"license_issuing_authority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"WA DLI "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"license_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Journey Level"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"license_source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"biz_owner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"licensee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"alias"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rooter-man-orting"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"website"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/adredir?ad_business_id=_Wv9uLrzQ1dZ6fgMYjgygg&amp;amp;campaign_id=jpQhVJGCG8ILi71Et0XDdQ&amp;amp;click_origin=search_results_visit_website&amp;amp;placement=vertical_0&amp;amp;placement_slot=1&amp;amp;redirect_url=https%3A%2F%2Fwww.yelp.com%2Fbiz_redir%3Fcachebuster%3D1701335261%26s%3D853c7f42baedaddb12d3a47cbf0c7c30e7bb3cf5d0408740f1e1ee56ec69c2a7%26src_bizid%3D_Wv9uLrzQ1dZ6fgMYjgygg%26url%3Dhttp%253A%252F%252Fwww.rooterman.com%26website_link_type%3Dwebsite&amp;amp;request_id=9d07f67caab0b9cc&amp;amp;signature=8842df091a5b79be57b4bf6122644039b1f6c07fac0c2fdb235c8ff076ce2520&amp;amp;slot=0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"rel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"noopener nofollow"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Orting"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"scrollablePhotos"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"isScrollable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"photoList"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://s3-media0.fl.yelpcdn.com/bphoto/-31eN7ypNCIJCHRO0Xjf3g/ls.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"srcset"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://s3-media0.fl.yelpcdn.com/bphoto/-31eN7ypNCIJCHRO0Xjf3g/258s.jpg 1.03x,https://s3-media0.fl.yelpcdn.com/bphoto/-31eN7ypNCIJCHRO0Xjf3g/300s.jpg 1.20x,https://s3-media0.fl.yelpcdn.com/bphoto/-31eN7ypNCIJCHRO0Xjf3g/348s.jpg 1.39x"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"photoHref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/adredir?ad_business_id=_Wv9uLrzQ1dZ6fgMYjgygg&amp;amp;campaign_id=jpQhVJGCG8ILi71Et0XDdQ&amp;amp;click_origin=search_results&amp;amp;placement=vertical_0&amp;amp;placement_slot=1&amp;amp;redirect_url=https%3A%2F%2Fwww.yelp.com%2Fbiz%2Frooter-man-orting%3Foverride_cta%3DGet%2Bpricing%2B%2526%2Bavailability&amp;amp;request_id=9d07f67caab0b9cc&amp;amp;signature=919646537897431750a9ec41b1240262d0e8596eed098a3d2776e9c9afe1898f&amp;amp;slot=0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"allPhotosHref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/biz_photos/_Wv9uLrzQ1dZ6fgMYjgygg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"isResponsive"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"childrenBusinessInfo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"searchResultBusinessPortfolioProjects"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"searchResultBusinessHighlights"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"bizSiteUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://biz.yelp.com/business_highlights?utm_source=disclaimer_www_searchresults"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"businessHighlights"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"bizPageIconName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"bizPageIconV2Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"40x40_locally_owned_v2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"iconName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"18x18_locally_owned"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LOCALLY_OWNED_OPERATED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Locally owned &amp;amp;amp; operated"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"bizPageIconName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"bizPageIconV2Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"40x40_family_owned_v2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"iconName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"18x18_family_owned"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FAMILY_OWNED_OPERATED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Family-owned &amp;amp;amp; operated"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"bizPageIconName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"bizPageIconV2Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"40x40_workmanship_guaranteed_v2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"iconName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"18x18_workmanship_guaranteed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"WORKMANSHIP_GUARANTEED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Workmanship guaranteed"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"bizPageIconName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"bizPageIconV2Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"40x40_years_in_business_v2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"iconName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"18x18_years_in_business"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YEARS_IN_BUSINESS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"20 years in business"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"bizPageIconName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"bizPageIconV2Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"40x40_veteran_owned_v2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"iconName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"18x18_veteran_owned"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VETERAN_OWNED_OPERATED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Veteran-owned &amp;amp;amp; operated"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"bizPageIconName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"bizPageIconV2Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"40x40_free_estimates_v2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"iconName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"18x18_free_estimates"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FREE_ESTIMATES"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Free estimates"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"numGemsAllowed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"serviceOfferings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"snippet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"readMoreText"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"more"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"readMoreUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/adredir?ad_business_id=_Wv9uLrzQ1dZ6fgMYjgygg&amp;amp;campaign_id=jpQhVJGCG8ILi71Et0XDdQ&amp;amp;click_origin=read_more&amp;amp;placement=vertical_0&amp;amp;placement_slot=1&amp;amp;redirect_url=https%3A%2F%2Fwww.yelp.com%2Fbiz%2Frooter-man-orting%3Foverride_cta%3DGet%2Bpricing%2B%2526%2Bavailability&amp;amp;request_id=9d07f67caab0b9cc&amp;amp;signature=919646537897431750a9ec41b1240262d0e8596eed098a3d2776e9c9afe1898f&amp;amp;slot=0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Give us a call for a free consultatiom."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"thumbnail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://s3-media0.fl.yelpcdn.com/bphoto/A0e8SoYZthSqITMDTjB0sA/30s.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"srcset"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://s3-media0.fl.yelpcdn.com/bphoto/A0e8SoYZthSqITMDTjB0sA/ss.jpg 1.33x,https://s3-media0.fl.yelpcdn.com/bphoto/A0e8SoYZthSqITMDTjB0sA/60s.jpg 2.00x,https://s3-media0.fl.yelpcdn.com/bphoto/A0e8SoYZthSqITMDTjB0sA/90s.jpg 3.00x"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"specialty"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"searchActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"markerKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ad_business:below_organic:U5LNtOZST6_9gpNAbqw8Lg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"searchResultLayoutType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"scrollablePhotos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"verifiedLicenseInfo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"licenses"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"licensee"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"licenseNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ROOTE**792MT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"issuedBy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"WA DLI "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"trade"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Journey Level"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"verifiedDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2023-11-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"expiryDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-08-12"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"bizSiteUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://biz.yelp.com/verified_license?utm_source=legal_disclaimer_www"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"verifiedLicenseLayout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BadgeAndTextBelowBizName"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"yelpGuaranteedInfo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"yelp_guaranteed_status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"yg_info_modal_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.yelp.com/yelp-guaranteed"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"adLoggingInfo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"placement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vertical_0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"slot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"placementSlot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"opportunityId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"9d07f67caab0b9cc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"adCampaignId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jpQhVJGCG8ILi71Et0XDdQ"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"flow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"search"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"isShowcaseAd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"offerCampaignDetails"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;....&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the sample output above, we can see that &lt;strong&gt;we have retrieved full business data from search pages directly in JSON&lt;/strong&gt;. Some attributes returned are even only available for the Yelp API through the enterprise plan!&lt;/p&gt;

&lt;p&gt;For further tips and tricks on Yelp web scraping, refer to our &lt;a href="https://scrapfly.io/blog/how-to-scrape-yelpcom/" rel="noopener noreferrer"&gt;dedicated guide&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scrape Yelp at Scale With ScrapFly
&lt;/h3&gt;

&lt;p&gt;We have seen that web scraping is a much better alternative to using Yelp API. However, there's a catch: &lt;a href="https://scrapfly.io/blog/how-to-scrape-without-getting-blocked-tutorial/" rel="noopener noreferrer"&gt;web scraping blocking&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Yelp is able to identify our web scraping requests as being automated and hence requiring us to solve CAPTCHA challenges or even blocking us entirely:&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2Fyelp-scraping-blocking-1.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2Fyelp-scraping-blocking-1.webp" alt="How to Use Yelp API to Extract Business and Review Data" width="800" height="438"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Yelp scraping blocking&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;ScrapFly provides &lt;a href="https://scrapfly.io/docs/scrape-api/getting-started" rel="noopener noreferrer"&gt;web scraping&lt;/a&gt;, &lt;a href="https://scrapfly.io/docs/screenshot-api/getting-started" rel="noopener noreferrer"&gt;screenshot&lt;/a&gt;, and &lt;a href="https://scrapfly.io/docs/extraction-api/getting-started" rel="noopener noreferrer"&gt;extraction&lt;/a&gt; APIs for data collection at scale.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/anti-scraping-protection" rel="noopener noreferrer"&gt;Anti-bot protection bypass&lt;/a&gt; - scrape web pages without blocking!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/proxy" rel="noopener noreferrer"&gt;Rotating residential proxies&lt;/a&gt; - prevent IP address and geographic blocks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-rendering" rel="noopener noreferrer"&gt;JavaScript rendering&lt;/a&gt; - scrape dynamic web pages through cloud browsers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-scenario" rel="noopener noreferrer"&gt;Full browser automation&lt;/a&gt; - control browsers to scroll, input and click on objects.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/getting-started#api_param_format" rel="noopener noreferrer"&gt;Format conversion&lt;/a&gt; - scrape as HTML, JSON, Text, or Markdown.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/sdk/python" rel="noopener noreferrer"&gt;Python&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/sdk/typescript" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt; SDKs, as well as &lt;a href="https://scrapfly.io/docs/sdk/scrapy" rel="noopener noreferrer"&gt;Scrapy&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/integration/getting-started" rel="noopener noreferrer"&gt;no-code tool integrations&lt;/a&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" alt="How to Use Yelp API to Extract Business and Review Data" width="876" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using ScrapFly to bypass Yelp scraping blocking is fairly straightforward. All we have to do is replace our HTTP client with ScrapFly client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# standard web scraping code
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;parsel&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Selector&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;httpx&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;some yelp.com URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;selector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# in ScrapFly becomes this 👇
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;scrapfly&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ScrapeConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ScrapflyClient&lt;/span&gt;

&lt;span class="c1"&gt;# replaces your HTTP client (httpx in this case)
&lt;/span&gt;&lt;span class="n"&gt;scrapfly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ScrapflyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your ScrapFly API key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scrapfly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scrape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ScrapeConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;website URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;asp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# enable the anti scraping protection to bypass blocking
&lt;/span&gt;    &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# set the proxy location to a specfic country
&lt;/span&gt;    &lt;span class="n"&gt;render_js&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt; &lt;span class="c1"&gt;# enable rendering JavaScript (like headless browsers) to scrape dynamic content if needed
&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# use the built in Parsel selector
&lt;/span&gt;&lt;span class="n"&gt;selector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selector&lt;/span&gt;
&lt;span class="c1"&gt;# access the HTML content
&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scrape_result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Refer to our official &lt;a href="https://github.com/scrapfly/scrapfly-scrapers/tree/main/yelp-scraper" rel="noopener noreferrer"&gt;official Yelp scraper on GitHub&lt;/a&gt; for ready-to-use data extraction scripts for various datasets.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;To wrap up this guide, let's look at some of the frequently asked questions about using Yelp API for data extraction.&lt;/p&gt;

&lt;h4&gt;
  
  
  Is Yelp API free?
&lt;/h4&gt;

&lt;p&gt;No, Yelp API is provided under paid subscription tiers. Each tier supports specific data resources.&lt;/p&gt;

&lt;h4&gt;
  
  
  Are there are alternatives for Yelp API?
&lt;/h4&gt;

&lt;p&gt;Yes, web scraping Yelp is a competitive alternative to Yelp API. This approach extracts Yelp data using HTLML parsing or by replicating background requests. Refer to our &lt;a href="https://scrapfly.io/blog/how-to-scrape-yelpcom/" rel="noopener noreferrer"&gt;Yelp scraping guide&lt;/a&gt; for more.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to get Yelp API key?
&lt;/h4&gt;

&lt;p&gt;Yelp requires API tokens to authorize its endpoints. To get your Yelp API key, subscribe to any of the &lt;a href="https://docs.developer.yelp.com/reference" rel="noopener noreferrer"&gt;available plans&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this guide, we went through an in-depth guide on Yelp API. We started by exploring the available API endpoints, their schemas, parameters, and outputs.&lt;/p&gt;

&lt;p&gt;We have seen that using Yelp API for data extraction has limitations, including expensive subscription plans and limited data attributes supported.&lt;/p&gt;

&lt;p&gt;As an alternative, we have explored &lt;a href="https://scrapfly.io/docs/scrape-api/getting-started" rel="noopener noreferrer"&gt;ScrapFly web scraping API&lt;/a&gt;. It provides antibot bypass capabilities, enabling Yelp data extraction at scale.&lt;/p&gt;

</description>
      <category>api</category>
    </item>
    <item>
      <title>What is Charles Proxy and How to Use it?</title>
      <dc:creator>Scrapfly</dc:creator>
      <pubDate>Wed, 06 Nov 2024 16:53:47 +0000</pubDate>
      <link>https://dev.to/scrapfly/what-is-charles-proxy-and-how-to-use-it-jd6</link>
      <guid>https://dev.to/scrapfly/what-is-charles-proxy-and-how-to-use-it-jd6</guid>
      <description>&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fwhat-is-charles-proxy-and-how-to-use-it_banner.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fwhat-is-charles-proxy-and-how-to-use-it_banner.svg" alt="What is Charles Proxy and How to Use it?" width="1910" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.charlesproxy.com/" rel="noopener noreferrer"&gt;Charles Proxy&lt;/a&gt; is a &lt;strong&gt;web debugging proxy&lt;/strong&gt; that enables developers to &lt;strong&gt;monitor&lt;/strong&gt; , &lt;strong&gt;inspect&lt;/strong&gt; and &lt;strong&gt;modify&lt;/strong&gt; HTTP/HTTPS traffic between their applications and remote servers.&lt;/p&gt;

&lt;p&gt;By acting as a man-in-the-middle proxy, Charles Proxy provides deep visibility into network communications that is essential for debugging APIs, analyzing web application behavior, and optimizing performance.&lt;/p&gt;

&lt;p&gt;This guide demonstrates how to &lt;strong&gt;effectively&lt;/strong&gt; use Charles Proxy for intercepting web traffic, debugging network issues, and testing applications. We'll cover setup configuration, key features, and practical examples of using Charles's inspection capabilities in real development workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Charles Proxy?
&lt;/h2&gt;

&lt;p&gt;Charles Proxy functions as a web debugging proxy server that runs locally on your machine. It positions itself between your &lt;strong&gt;web browser/application&lt;/strong&gt; and &lt;strong&gt;the internet&lt;/strong&gt;, enabling developers to monitor, inspect and modify all HTTP/HTTPS network traffic.&lt;/p&gt;

&lt;p&gt;When configured, your browser routes all requests through Charles before they reach their destination servers, allowing you to examine the complete request and response cycle.&lt;/p&gt;

&lt;p&gt;The proxy server captures critical debugging data including HTTP headers, cookies, SSL certificates, and request/response bodies. This visibility into the network layer helps developers troubleshoot API integrations, analyze web application behavior, and optimize network performance.&lt;/p&gt;

&lt;p&gt;Charles Proxy can also capture Android and iOS app traffic though in this tutorial we'll focus on web traffic interception.&lt;/p&gt;

&lt;h2&gt;
  
  
  Man In the Middle Proxy Uses
&lt;/h2&gt;

&lt;p&gt;Charles Proxy's man-in-the-middle capabilities enable several critical debugging and development workflows:&lt;/p&gt;

&lt;h3&gt;
  
  
  Network Traffic Analysis
&lt;/h3&gt;

&lt;p&gt;By intercepting requests between clients and servers, developers can inspect the exact data being transmitted, including headers, parameters, and payloads. This visibility helps diagnose API integration issues, validate request/response formats, and verify data handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security Testing
&lt;/h3&gt;

&lt;p&gt;Security engineers use Charles to analyze application security by examining encryption implementations, testing for vulnerabilities, and validating certificate handling. The ability to modify requests allows testing of input validation and security controls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance Optimization
&lt;/h3&gt;

&lt;p&gt;The proxy enables measurement of request timing, payload sizes, and connection behavior. Developers can identify slow requests, unnecessary data transfers, and connection bottlenecks. The bandwidth throttling feature helps test application behavior under constrained network conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mobile App Development
&lt;/h3&gt;

&lt;p&gt;Charles facilitates debugging of mobile applications by providing visibility into network calls made from iOS and Android devices. This helps developers troubleshoot API integrations, analyze caching behavior, and optimize mobile data usage.&lt;/p&gt;

&lt;h3&gt;
  
  
  API Development and Testing
&lt;/h3&gt;

&lt;p&gt;When building APIs, Charles allows developers to inspect the exact requests clients make and responses servers return. This helps validate API implementations, debug client integration issues, and ensure proper data formatting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Web Application Debugging
&lt;/h3&gt;

&lt;p&gt;Front-end developers use Charles to debug AJAX requests, analyze REST API calls, and troubleshoot browser-server communications. The ability to modify requests helps test different scenarios without changing application code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Charles Proxy
&lt;/h2&gt;

&lt;p&gt;Getting started with Charles requires configuring both your system and the applications you want to debug. The setup process involves installing Charles, configuring your browser/device to route traffic through Charles, and setting up SSL certificates for HTTPS inspection.&lt;/p&gt;

&lt;p&gt;First, download and install Charles from the &lt;a href="https://www.charlesproxy.com/download/" rel="noopener noreferrer"&gt;official download page&lt;/a&gt;. By default, Charles runs on port 8888 and attempts to automatically configure your system's proxy settings. You can verify Charles is working by opening your browser - you should see web traffic appearing in Charles's main window.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-12.54.39-AM-1.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-12.54.39-AM-1.webp" alt="What is Charles Proxy and How to Use it?" width="800" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, all the intercepted requests fall under the "Encrypted" category. This is because most of the websites we visit today use HTTPS, which encrypts both requests and responses to prevent spoofing or tampering.&lt;/p&gt;

&lt;p&gt;However, Charles proxy allow us to install an SSL certificate that is able to decrypt HTTPS requests and make them inspectable.&lt;/p&gt;

&lt;h3&gt;
  
  
  SSL Certificates
&lt;/h3&gt;

&lt;p&gt;To inspect HTTPS traffic, Charles generates a unique root certificate for your installation that must be trusted by your system and devices. This enables Charles to decrypt and inspect encrypted traffic by acting as a trusted certificate authority.&lt;/p&gt;

&lt;p&gt;The certificate installation process on windows and macOS are very similar, so we are going to demonstrate it on macOS.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Help &amp;gt; SSL Proxying &amp;gt; Install Charles Root Certificate &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-1.10.15-AM.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-1.10.15-AM.webp" alt="charles proxy root certificate install option" width="800" height="513"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enter your device credentials to authorize the installation &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-1.13.48-AM.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-1.13.48-AM.webp" alt="charles proxy authorization request" width="536" height="640"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install the certificate under "login" keychains &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-1.17.43-AM.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-1.17.43-AM.webp" alt="charles proxy login key chain install on macos" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Double tap the certificate &amp;gt; Expand the "Trust" tab &amp;gt; Set "When using this certificate" to "Always Trust" &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-1.26.17-AM.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-1.26.17-AM.webp" alt="charles proxy certificate trust option" width="800" height="688"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Close the window and save the changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  For Mobile Devices:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;iOS: Visit chls.pro/ssl while connected through Charles&lt;/li&gt;
&lt;li&gt;Android: Export the certificate from Charles and manually install it in device settings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The certificate is uniquely generated for your Charles installation to maintain security. Charles maintains end-to-end encryption by establishing separate SSL connections with both client and server. After installing the certificate:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You can enable SSL proxying on specific domains by right-clicking the domain name and click "Enable SSL Proxying"&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-1.37.19-AM.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-1.37.19-AM.webp" alt="charles proxy enable ssl proxy option" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to Proxy &amp;gt; SSL Proxying Settings and add entries to the list of domains you want to include in SSL Proxying.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-3.33.21-AM.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-3.33.21-AM.webp" alt="charles proxy SSL proxy settings page" width="800" height="591"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Using Charles Proxy to Intercept Web Traffic
&lt;/h2&gt;

&lt;p&gt;Charles Proxy provides comprehensive web debugging capabilities through its traffic interception features. The proxy server captures all HTTP/HTTPS requests and responses, displaying them in a structured interface that enables detailed inspection and analysis.&lt;/p&gt;

&lt;p&gt;When traffic flows through Charles, each request appears in the main window with key details like the host, path, method, and status code.Selecting a request reveals the complete headers, parameters, and body content in the request/response panels.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-3.37.50-AM.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-3.37.50-AM.webp" alt="charles proxy web traffic interception page" width="800" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This granular visibility helps developers identify issues in API calls, validate data formats, and troubleshoot network errors.&lt;/p&gt;

&lt;p&gt;There two options to view the requests intercepted by Charles Proxy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Structure&lt;/strong&gt; view organizes requests by domain and displays them in a tree format, making it easy to focus on specific hosts or endpoints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Sequence view&lt;/strong&gt; shows requests chronologically with timing information to analyze request patterns and identify performance bottlenecks.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For modifying traffic, Charles provides breakpoints that pause requests before they reach the server or responses before they return to the client. This enables testing different scenarios by editing parameters, headers, or response data. Map Local and Rewrite rules offer persistent request/response modifications without manual intervention.&lt;/p&gt;

&lt;p&gt;Charles also includes specialized tools for web debugging like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Throttling bandwidth and adding latency to simulate poor network conditions&lt;/li&gt;
&lt;li&gt;Validating response content against W3C standards&lt;/li&gt;
&lt;li&gt;Comparing requests to identify differences&lt;/li&gt;
&lt;li&gt;Recording and replaying captured traffic for reproducible testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These capabilities make Charles an invaluable tool for debugging web applications, APIs, and network communications during development and testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web Scraping with Charles Proxy
&lt;/h2&gt;

&lt;p&gt;Charles Proxy streamlines web scraping development by providing detailed visibility into web requests. The proxy captures all request components including headers, cookies, and parameters that need to be replicated in scraping code. This visibility eliminates guesswork when reproducing browser requests programmatically.&lt;/p&gt;

&lt;p&gt;The proxy's traffic interception reveals how websites implement anti-bot measures like dynamic tokens or session handling. Developers can analyze these protection mechanisms and implement appropriate countermeasures in their scraping logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Example
&lt;/h3&gt;

&lt;p&gt;We can demonstrate how Charles Proxy can be used for web scraping tasks by intercepting the requests sent by the testimonials page in &lt;a href="https://web-scraping.dev/testimonials" rel="noopener noreferrer"&gt;web-scraping.dev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The testimonials page initially includes 10 testimonials and loads more testimonials as the user scrolls to the bottom of the page.&lt;/p&gt;

&lt;p&gt;We can use Charles Proxy to intercept the requests sent by the page to load more testimonials.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-3.50.13-AM.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-3.50.13-AM.webp" alt="charles proxy example interception for web-scraping.dev test page" width="800" height="677"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that the website sends requests to &lt;code&gt;https://web-scraping.dev/api/testimonials?page=[pageNumber]&lt;/code&gt; to load more testimonials on each scroll; and we can copy this request as a cURL command (by right-clicking on it) to replicate it with the same configuration sent by the parent website (headers, parameters, body...)&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-3.55.00-AM.webp" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2F2024%2F11%2FScreenshot-2024-11-05-at-3.55.00-AM.webp" alt="charles proxy copy cURL Request example" width="800" height="642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scrapfly provides a useful &lt;a href="https://scrapfly.io/web-scraping-tools/curl-python" rel="noopener noreferrer"&gt;tool&lt;/a&gt; that converts cURL commands into executable code using Python's most popular HTTP clients. You can use it to integrate requests intercepted by Charles Proxy into your python web crawler.&lt;/p&gt;

&lt;h2&gt;
  
  
  Power Up with Scrapfly
&lt;/h2&gt;

&lt;p&gt;Charles Proxy is a great tool for debugging and analyzing web traffic though to take advantage of this information for web scraping or web automation tasks you'll still need to write code to replicate the requests and handle the responses. This is where Scrapfly can assist you!&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" alt="scrapfly middleware" width="876" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ScrapFly provides &lt;a href="https://scrapfly.io/docs/scrape-api/getting-started" rel="noopener noreferrer"&gt;web scraping&lt;/a&gt;, &lt;a href="https://scrapfly.io/docs/screenshot-api/getting-started" rel="noopener noreferrer"&gt;screenshot&lt;/a&gt;, and &lt;a href="https://scrapfly.io/docs/extraction-api/getting-started" rel="noopener noreferrer"&gt;extraction&lt;/a&gt; APIs for data collection at scale.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/anti-scraping-protection" rel="noopener noreferrer"&gt;Anti-bot protection bypass&lt;/a&gt; - scrape web pages without blocking!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/proxy" rel="noopener noreferrer"&gt;Rotating residential proxies&lt;/a&gt; - prevent IP address and geographic blocks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-rendering" rel="noopener noreferrer"&gt;JavaScript rendering&lt;/a&gt; - scrape dynamic web pages through cloud browsers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-scenario" rel="noopener noreferrer"&gt;Full browser automation&lt;/a&gt; - control browsers to scroll, input and click on objects.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/getting-started#api_param_format" rel="noopener noreferrer"&gt;Format conversion&lt;/a&gt; - scrape as HTML, JSON, Text, or Markdown.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/sdk/python" rel="noopener noreferrer"&gt;Python&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/sdk/typescript" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt; SDKs, as well as &lt;a href="https://scrapfly.io/docs/sdk/scrapy" rel="noopener noreferrer"&gt;Scrapy&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/integration/getting-started" rel="noopener noreferrer"&gt;no-code tool integrations&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Charles Proxy Issues
&lt;/h2&gt;

&lt;p&gt;When troubleshooting Charles Proxy, these issues commonly arise:&lt;/p&gt;

&lt;h4&gt;
  
  
  SSL Certificate Problems
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Browser warnings appear when Charles's root certificate isn't properly installed/trusted&lt;/li&gt;
&lt;li&gt;Chrome on localhost requires enabling insecure localhost in chrome://flags&lt;/li&gt;
&lt;li&gt;Mobile devices need manual certificate installation through chls.pro/ssl&lt;/li&gt;
&lt;li&gt;Certificate pinning in some apps prevents SSL inspection&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Network Configuration Issues
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Applications fail to connect when proxy settings are incorrect (verify 127.0.0.1:8888)&lt;/li&gt;
&lt;li&gt;Forgetting to disable proxy settings after debugging causes connection failures&lt;/li&gt;
&lt;li&gt;iOS devices experience network problems if proxy config isn't removed post-debugging&lt;/li&gt;
&lt;li&gt;External proxy conflicts when Charles is configured with another proxy server&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Performance and Memory
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;SSL proxying on many hosts causes slowdown - limit wildcards (*) usage&lt;/li&gt;
&lt;li&gt;Large response bodies impact memory usage - clear session periodically&lt;/li&gt;
&lt;li&gt;High traffic applications may require increased memory allocation&lt;/li&gt;
&lt;li&gt;Throttling feature can unexpectedly slow all network traffic&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Application-Specific Challenges
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Android apps require custom network security config for certificate trust&lt;/li&gt;
&lt;li&gt;Some applications use certificate pinning requiring code modifications&lt;/li&gt;
&lt;li&gt;WebSocket connections may fail without proper SSL proxying configuration&lt;/li&gt;
&lt;li&gt;HTTP/2 traffic sometimes requires specific SSL proxying settings&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Charles Proxy is a versatile tool that empowers developers with the ability to intercept, inspect, and manipulate network traffic. Its robust features make it ideal for debugging web applications, testing APIs, and supporting web scraping efforts. Key capabilities include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Traffic Inspection&lt;/strong&gt; : View detailed request/response data to troubleshoot client-server interactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL Support&lt;/strong&gt; : Intercept secure HTTPS traffic with certificate handling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request Mapping &amp;amp; Modification&lt;/strong&gt; : Offers tools to map requests to different endpoints or local files, enabling testing under diverse scenarios without altering the actual server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Throttling &amp;amp; Breakpoints&lt;/strong&gt; : Simulate network conditions and pause requests for precise debugging.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With careful configuration, Charles Proxy is a powerful addition to any web developer’s toolkit.&lt;/p&gt;

</description>
      <category>tools</category>
      <category>proxies</category>
    </item>
    <item>
      <title>Axios vs Fetch: Which HTTP Client to Choose in JS?</title>
      <dc:creator>Scrapfly</dc:creator>
      <pubDate>Tue, 29 Oct 2024 06:57:49 +0000</pubDate>
      <link>https://dev.to/scrapfly/axios-vs-fetch-which-http-client-to-choose-in-js-1d3n</link>
      <guid>https://dev.to/scrapfly/axios-vs-fetch-which-http-client-to-choose-in-js-1d3n</guid>
      <description>&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Faxios-vs-fetch_banner.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Faxios-vs-fetch_banner.svg" alt="Axios vs Fetch: Which HTTP Client to Choose in JS?" width="1910" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Making HTTP requests is a fundamental feature in any programming language, and JavaScript is no exception. As the development community has moved away from using &lt;code&gt;XMLHttpRequest&lt;/code&gt;, making HTTP requests in JavaScript typically involves either the built-in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API" rel="noopener noreferrer"&gt;Fetch API&lt;/a&gt; or the &lt;a href="https://www.npmjs.com/package/axios" rel="noopener noreferrer"&gt;axios package&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore Fetch vs Axios — compare their key differences, pros, cons, and help you determine which option is best for your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Fetch?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fetch&lt;/strong&gt; is a built-in browser API that allows you to make HTTP requests from the client side, providing a more modern and flexible alternative to the older &lt;code&gt;XMLHttpRequest&lt;/code&gt;. It is known for its &lt;strong&gt;promise-based&lt;/strong&gt; syntax, making it easy to handle asynchronous operations. While Fetch was initially designed for the browser environment, it has also been officially supported in &lt;strong&gt;Node.js v18&lt;/strong&gt;. This means developers can now use Fetch in both the browser and server-side environments, making it a versatile tool for modern JavaScript development.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ Fetch is also supported by other JS runtimes like &lt;a href="https://bun.sh/docs/api/fetch" rel="noopener noreferrer"&gt;Bun&lt;/a&gt; and &lt;a href="https://docs.deno.com/api/web/~/fetch" rel="noopener noreferrer"&gt;Deno&lt;/a&gt; as well as serverless runtimes like &lt;a href="https://developers.cloudflare.com/workers/runtime-apis/fetch/" rel="noopener noreferrer"&gt;Cloudflare Workers&lt;/a&gt; and &lt;a href="https://edge-runtime.vercel.app/features/available-apis" rel="noopener noreferrer"&gt;Edge Runtime&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Example of a basic Fetch request using .then() syntax and async/await syntax:&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://httpbin.dev/json&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;response&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;fetch&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://httpbin.dev/json&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;data&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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;main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Fetch API’s integration in Node.js allows developers to work with the same API on both client and server sides, simplifying the codebase and making Fetch a powerful tool across the entire stack that is now considered a default option for handling HTTP requests in many JavaScript applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Axios?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Axios&lt;/strong&gt; is a popular third-party HTTP client library that simplifies making HTTP requests in JavaScript. Built on top of JavaScript’s &lt;code&gt;XMLHttpRequest&lt;/code&gt; interface in the browser and Node.js’s &lt;code&gt;http&lt;/code&gt; module on the server, Axios provides a cleaner and more intuitive syntax for making requests and handling responses.&lt;/p&gt;

&lt;p&gt;Example of a basic Axios request using .then() syntax and async/await syntax:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;axios&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/data&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;response&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="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;response&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;axios&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com/data&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;response&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="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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;main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fetch vs Axios - How are They Different?
&lt;/h2&gt;

&lt;p&gt;Both Fetch and Axios are capable of handling HTTP requests, but they differ in several key areas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Availability
&lt;/h3&gt;

&lt;p&gt;Fetch is a built-in API available in the browser, Node.js, and most JS runtimes and serverless environments making it one less dependency for your project.In contrast, Axios is a third-party library, meaning it requires installation via a package manager or inclusion through a CDN.&lt;/p&gt;

&lt;p&gt;While both axios and fetch are isomorphic, meaning that they can be used in both server and client-side environments, each supports a different yet overlapping set of browsers, node.js versions, and JS runtimes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Axios&lt;/th&gt;
&lt;th&gt;Fetch&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Client-side Availability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Available via npm/CDN&lt;/td&gt;
&lt;td&gt;Built into modern browsers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Browser Compatibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fully Compatible (including IE11)&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://caniuse.com/fetch" rel="noopener noreferrer"&gt;All Modern browsers&lt;/a&gt; (No IE11 support)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Polyfill Requirements&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Requires &lt;a href="https://axios-http.com/docs/notes#promises" rel="noopener noreferrer"&gt;ES6 promises polyfill&lt;/a&gt; for non ES6 environments&lt;/td&gt;
&lt;td&gt;Requires &lt;a href="https://github.com/JakeChampion/fetch" rel="noopener noreferrer"&gt;polyfill&lt;/a&gt; for IE11 and older browsers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Server Runtime Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;- Native support since Node.js 18 (May 2022) - Stable since Node.js 21 (Nov 2023) - Earlier versions require &lt;code&gt;node-fetch&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deno&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bun&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Serverless Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS Lambda&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Azure Functions&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Cloud Functions&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloudflare Workers&lt;/td&gt;
&lt;td&gt;🚫&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Netlify Functions&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Netlify Edge Functions&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vercel Serverless Funcitons (Node.js)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vercel Edge Functions (Edge Runtime)&lt;/td&gt;
&lt;td&gt;🚫&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deno Deploy&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;p&gt;While fetch Provides basic functionality for making HTTP requests, it lacks many built-in advanced features that axios supports by default. Let's explore some of those features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Interceptors&lt;/strong&gt;&lt;br&gt;
Interceptors in Axios allow you to modify requests and responses before they are processed. They are particularly useful for tasks like adding authentication tokens, logging requests, or handling global error responses.&lt;/p&gt;

&lt;p&gt;Using interceptors you can centralize logic that applies to all requests or responses, enhancing maintainability and flexibility in your application.&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="c1"&gt;// Add a request interceptor&lt;/span&gt;
&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&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="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Do something before request is sent&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Do something with request error&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Add a response interceptor&lt;/span&gt;
&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Any status code that lie within the range of 2xx cause this function to trigger&lt;/span&gt;
    &lt;span class="c1"&gt;// Do something with response data&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Any status codes that falls outside the range of 2xx cause this function to trigger&lt;/span&gt;
    &lt;span class="c1"&gt;// Do something with response error&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;p&gt;&lt;strong&gt;2. Timeouts&lt;/strong&gt;&lt;br&gt;
Timeouts in Axios provide a way to control how long the client should wait for a server response before aborting the request. This is essential when dealing with unreliable networks or APIs that may take too long to respond.&lt;/p&gt;

&lt;p&gt;With Axios, you can easily configure request timeouts to ensure your app doesn't hang indefinitely waiting for a response.&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="c1"&gt;// Setting a timeout of 5 seconds (5000 milliseconds)&lt;/span&gt;
&lt;span class="nx"&gt;axios&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://httpbin.dev/json&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="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="nx"&gt;response&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="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ECONNABORTED&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Request timed out&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;else&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Query parameters serialization&lt;/strong&gt;&lt;br&gt;
Query parameters allow you to pass data in the URL of a GET request. They are typically used to pass additional configuration options for an endpoint, such as filters and pagination.&lt;/p&gt;

&lt;p&gt;Axios makes it simple to serialize query parameters into the proper format, ensuring they are correctly appended to the URL. It also supports serlializing nested objects without reaching out to a third party library like &lt;a href="https://www.npmjs.com/package/qs" rel="noopener noreferrer"&gt;qs&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;page&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="na"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;desc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apparel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;axios&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://web-scraping.dev/api/products&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;params&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="nx"&gt;response&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="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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;p&gt;&lt;strong&gt;4. Automatic request body serialization&lt;/strong&gt;&lt;br&gt;
Request body serialization depends on the type of content sent in the body. Whether it's JSON, URL-encoded data, or multipart form data, each type has its very own serialization technique.&lt;/p&gt;

&lt;p&gt;Axios automatically converts the request body to the appropriate format based on the content type, eliminating the hassle of manually handling it using built-in language features like &lt;code&gt;JSON.stringify&lt;/code&gt; or third-party libraries.&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="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="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;occupation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Developer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Default (application/json)&lt;/span&gt;
&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://httpbin.dev/post&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;response&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="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// 'application/x-www-form-urlencoded'&lt;/span&gt;
&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://httpbin.dev/post&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;headers&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;Content-Type&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;application/x-www-form-urlencoded&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;response&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;//'multipart/form-data'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formData&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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;profile_picture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&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;#fileInput&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://httpbin.dev/post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;headers&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;Content-Type&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;multipart/form-data&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;response&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Automatic Response Parsing&lt;/strong&gt;&lt;br&gt;
Automatic response parsing refers to Axios's ability to automatically parse the server's response into the appropriate data format.&lt;/p&gt;

&lt;p&gt;If the response is in a valid JSON object, Axios will parse it into a JavaScript object without requiring you to manually call .json(), making it easier to handle responses with minimal effort.&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="nx"&gt;axios&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://httpbin.dev/json&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="nx"&gt;response&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="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// compared to fetch&lt;/span&gt;
&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://httpbin.dev/json&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// a bit more verbose compared to axios&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="nx"&gt;data&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;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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;p&gt;&lt;strong&gt;6. Progress capturing&lt;/strong&gt;&lt;br&gt;
Tracking the progress of data uploads and downloads in real-time is a very common task encountered by developers. Unfortunately, fetch doesn't support progress tracking and implementing a solution around will lead you into a bunch of browser compatibility issues.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;onUploadProgress&lt;/code&gt; and &lt;code&gt;onDownloadProgress&lt;/code&gt; callbacks in Axios, you can easily monitor how much data has been transferred to and from the server, which is especially useful when dealing with large files or slow network conditions.&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="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://httpbin.dev/post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;headers&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;Content-Type&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;multipart/form-data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;onUploadProgress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;progressEvent&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;percentCompleted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;progressEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loaded&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;progressEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&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="s2"&gt;`Upload Progress: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;percentCompleted&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="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;response&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="nx"&gt;axios&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/content.txt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="nx"&gt;onDownloadProgress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;progressEvent&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;percentCompleted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;progressEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loaded&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;progressEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&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="s2"&gt;`Download Progress: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;percentCompleted&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="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;response&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although axios has built-in support for all those features, they can all be easily implemented in fetch with some boilerplate code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Developer Experience
&lt;/h3&gt;

&lt;p&gt;When comparing Fetch and Axios from a user experience perspective, &lt;strong&gt;Axios offers a more streamlined and feature-rich approach&lt;/strong&gt; providing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;automatic JSON parsing&lt;/li&gt;
&lt;li&gt;built-in error handling&lt;/li&gt;
&lt;li&gt;and more features like interceptors and request cancellation.
This reduces boilerplate code and makes it easier to handle complex HTTP requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In contrast, &lt;strong&gt;Fetch is more minimalistic but more readily available&lt;/strong&gt; and requires manual handling for tasks like transforming data and checking for non-2xx status codes, leading to more verbose code.&lt;/p&gt;

&lt;p&gt;While Fetch offers flexibility and is natively supported in browsers, Axios enhances productivity by offering a cleaner, more user-friendly API, particularly for complex requests.&lt;/p&gt;

&lt;p&gt;Axios’s ability to handle global configuration, error management, and response transformations makes it a more developer-friendly choice for larger applications, while Fetch might be more suited for simpler, straightforward tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;In terms of performance, there is generally &lt;strong&gt;no significant difference&lt;/strong&gt; between Fetch and Axios for most typical HTTP requests. Both tools handle HTTP requests efficiently, and any performance differences are usually negligible in real-world applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points to Consider:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fetch&lt;/strong&gt; is a native browser API, which means it’s lightweight and directly integrated into the browser’s environment. This can make Fetch slightly faster in some cases due to the lack of external dependencies, especially for simple requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Axios&lt;/strong&gt; , being a third-party library, introduces a tiny amount of overhead because it has additional features built on top of the basic request-handling mechanisms. However, this overhead is minimal and usually doesn't impact performance significantly, especially when the added convenience and functionality of Axios are considered.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For basic use cases, Fetch might have a slight performance advantage due to its lightweight nature, but for more complex tasks, Axios provides a smoother experience with minimal performance impact.&lt;/p&gt;

&lt;p&gt;In most cases, the performance &lt;em&gt;difference is so small&lt;/em&gt; that the choice between Fetch and Axios should be based on functionality and developer experience rather than speed alone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Axios Alternatives
&lt;/h3&gt;

&lt;p&gt;While &lt;strong&gt;Axios&lt;/strong&gt; remains one of the most popular HTTP libraries, several modern alternatives provide similar functionality, often with added features or optimizations. Some modern alternatives include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/ladjs/superagent" rel="noopener noreferrer"&gt;&lt;strong&gt;Superagent&lt;/strong&gt;&lt;/a&gt;: A flexible and powerful HTTP request library that provides a simple API for making requests in both Node.js and browsers. It supports promises, streams, and file uploads.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sindresorhus/got" rel="noopener noreferrer"&gt;&lt;strong&gt;Got&lt;/strong&gt;&lt;/a&gt;: A lightweight and feature-rich HTTP request library for Node.js. It’s known for its powerful error handling, high-performance, and promise-based API. It also offers advanced features like retry mechanisms, hooks, and custom agents.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sindresorhus/ky" rel="noopener noreferrer"&gt;&lt;strong&gt;Ky&lt;/strong&gt;&lt;/a&gt;: By the maker of &lt;strong&gt;Got&lt;/strong&gt;. A smaller, modern wrapper around Fetch designed for browsers. It’s promise-based, tiny in size, and offers features like automatic JSON parsing, retry logic, and simpler syntax than vanilla Fetch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these alternatives provides different features, and the best choice depends on your project’s specific requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Power Up with Scrapfly
&lt;/h2&gt;

&lt;p&gt;While both Fetch and Axios are excellent HTTP clients they are not ideal for tasks like web automation and web scraping.&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" alt="Axios vs Fetch: Which HTTP Client to Choose in JS?" width="876" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ScrapFly provides &lt;a href="https://scrapfly.io/docs/scrape-api/getting-started" rel="noopener noreferrer"&gt;web scraping&lt;/a&gt;, &lt;a href="https://scrapfly.io/docs/screenshot-api/getting-started" rel="noopener noreferrer"&gt;screenshot&lt;/a&gt;, and &lt;a href="https://scrapfly.io/docs/extraction-api/getting-started" rel="noopener noreferrer"&gt;extraction&lt;/a&gt; APIs for data collection at scale.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/anti-scraping-protection" rel="noopener noreferrer"&gt;Anti-bot protection bypass&lt;/a&gt; - scrape web pages without blocking!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/proxy" rel="noopener noreferrer"&gt;Rotating residential proxies&lt;/a&gt; - prevent IP address and geographic blocks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-rendering" rel="noopener noreferrer"&gt;JavaScript rendering&lt;/a&gt; - scrape dynamic web pages through cloud browsers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-scenario" rel="noopener noreferrer"&gt;Full browser automation&lt;/a&gt; - control browsers to scroll, input and click on objects.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/getting-started#api_param_format" rel="noopener noreferrer"&gt;Format conversion&lt;/a&gt; - scrape as HTML, JSON, Text, or Markdown.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/sdk/python" rel="noopener noreferrer"&gt;Python&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/sdk/typescript" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt; SDKs, as well as &lt;a href="https://scrapfly.io/docs/sdk/scrapy" rel="noopener noreferrer"&gt;Scrapy&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/integration/getting-started" rel="noopener noreferrer"&gt;no-code tool integrations&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;Before we wrap this article up let's take a look at some frequently asked questions regarding fetch and axios comparisson that we haven't covered in this article:&lt;/p&gt;

&lt;h4&gt;
  
  
  Is axios better than fetch?
&lt;/h4&gt;

&lt;p&gt;Whether Axios is better than Fetch depends on your needs. Axios offers a more feature-rich, user-friendly experience making it a powerful choice for handling complex HTTP requests. However, Fetch is a native browser API, which makes it lightweight and ideal for simple requests. It’s flexible, built into modern browsers, and requires no additional dependencies, making it more suitable for smaller projects or when simplicity is preferred.&lt;/p&gt;

&lt;h4&gt;
  
  
  What is the difference between node-fetch and fetch?
&lt;/h4&gt;

&lt;p&gt;Before Fetch was natively supported in Node.js as of version 18, &lt;code&gt;node-fetch&lt;/code&gt; was required for Fetch-like functionality on the server. &lt;code&gt;node-fetch&lt;/code&gt; is a lightweight module that brings the Fetch API to Node.js environments, allowing server-side JavaScript to make HTTP requests in a similar way.&lt;/p&gt;

&lt;h4&gt;
  
  
  Can Fetch and Axios be used in web scraping?
&lt;/h4&gt;

&lt;p&gt;Just like any http client, Fetch and Axios can both be used to request webpages or REST APIs for the purpose of scraping data. Check out our &lt;a href="https://scrapfly.io/blog/web-scraping-with-nodejs/" rel="noopener noreferrer"&gt;dedicated article&lt;/a&gt; on web scarping with Node.js and Javascript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In summary, both &lt;strong&gt;Fetch&lt;/strong&gt; and &lt;strong&gt;Axios&lt;/strong&gt; are powerful tools for making HTTP requests in JavaScript, each with unique advantages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fetch&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Native to browsers, Node.js (from v18 onwards), and mainstream JS runtimes and serverless environments&lt;/li&gt;
&lt;li&gt;Lightweight and ideal for simpler requests with minimal configuration.&lt;/li&gt;
&lt;li&gt;Requires more manual handling for JSON parsing, error handling, and advanced features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Axios&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Third-party library with more features for handling complex requests.&lt;/li&gt;
&lt;li&gt;Provides automatic JSON parsing, built-in error handling, request cancellation, and interceptors.&lt;/li&gt;
&lt;li&gt;More user-friendly and efficient for large-scale applications needing advanced configurations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ultimately, the choice between Fetch and Axios should be based on the specific needs of your project, balancing simplicity with functionality.&lt;/p&gt;

</description>
      <category>http</category>
      <category>node</category>
      <category>api</category>
    </item>
    <item>
      <title>What is HTTP 415 Error? (Unsupported Media Type)</title>
      <dc:creator>Scrapfly</dc:creator>
      <pubDate>Thu, 24 Oct 2024 15:24:53 +0000</pubDate>
      <link>https://dev.to/scrapfly/what-is-http-415-error-unsupported-media-type-31on</link>
      <guid>https://dev.to/scrapfly/what-is-http-415-error-unsupported-media-type-31on</guid>
      <description>&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fwhat-is-http-415-error-unsupported-media-type_banner.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fwhat-is-http-415-error-unsupported-media-type_banner.svg" alt="What is HTTP 415 Error? (Unsupported Media Type)" width="1600" height="836"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Encountering an HTTP error can disrupt your web scraping or automation tasks, and HTTP error 415 is one such issue that indicates a problem with the type of data being sent.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore what HTTP 415 is, the common causes behind it, how to replicate it, and whether it could be used as a blocking mechanism.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is HTTP Error 415?
&lt;/h2&gt;

&lt;p&gt;HTTP error 415 &lt;code&gt;Unsupported Media Type&lt;/code&gt;, occurs when the server refuses to process a request because the format or media type of the data being sent is not supported. For example, if you try to send JSON data to an endpoint that only accepts XML, you would encounter a 415 error.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are HTTP 415 Error Causes?
&lt;/h2&gt;

&lt;p&gt;The most common cause of a 415 error is &lt;em&gt;sending data in an unsupported format&lt;/em&gt;. This can happen when the &lt;code&gt;Content-Type&lt;/code&gt; header in the request does not match the media type that the server expects.&lt;/p&gt;

&lt;p&gt;For instance, if you're sending a POST request with &lt;code&gt;application/xml&lt;/code&gt; but the server expects &lt;code&gt;application/json&lt;/code&gt;, you’ll trigger a 415 error.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Example
&lt;/h3&gt;

&lt;p&gt;Let's explore how to configure headers, specifically &lt;code&gt;Content-Type&lt;/code&gt; headers, in common tools like python's httpx library, and cURL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;

&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://httpbin.dev/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; &lt;span class="s2"&gt;"POST"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; https://httpbin.dev/json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the examples above, the client is specifying that the body content is in &lt;code&gt;application/json&lt;/code&gt; format. If the server expects a different media-type than the one that the client specified, a 415 error might occur.&lt;/p&gt;

&lt;p&gt;To avoid 415 errors, ensure that your &lt;code&gt;Content-Type&lt;/code&gt; header is set appropriately for the endpoint your are sending data to.&lt;/p&gt;

&lt;h2&gt;
  
  
  415 in Web Scraping
&lt;/h2&gt;

&lt;p&gt;Http status 415 in web scraping is usually encountered when scraping &lt;code&gt;POST&lt;/code&gt; or &lt;code&gt;PUT&lt;/code&gt; type endpoints like search queries or form submissions. For these cases it's important to set the correct &lt;code&gt;Content-Type&lt;/code&gt; header that not only matches the sent content type but the type server expects. To verify what content type the server expects, you can use &lt;a href="https://scrapfly.io/blog/browser-developer-tools-in-web-scraping/" rel="noopener noreferrer"&gt;Browser Developer Tools&lt;/a&gt; and inspect browser requests.&lt;/p&gt;

&lt;p&gt;Another posibility is that the server is blocking your scraper requests and returns status code 415 purposefully to block your scraper. This is quite rare but here are some indicators that http code 415 is a block:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;415 is returned on &lt;code&gt;GET&lt;/code&gt; or &lt;code&gt;HEAD&lt;/code&gt; requests&lt;/li&gt;
&lt;li&gt;415 error cannot be replicated for the same identical requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you suspect that you are being blocked take a look at our &lt;a href="https://scrapfly.io/blog/how-to-scrape-without-getting-blocked-tutorial/" rel="noopener noreferrer"&gt;guide on web scraping blocking&lt;/a&gt; or try Scrapfly Web Scraping API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Power Up with Scrapfly
&lt;/h2&gt;

&lt;p&gt;ScrapFly provides &lt;a href="https://scrapfly.io/docs/scrape-api/getting-started" rel="noopener noreferrer"&gt;web scraping&lt;/a&gt;, &lt;a href="https://scrapfly.io/docs/screenshot-api/getting-started" rel="noopener noreferrer"&gt;screenshot&lt;/a&gt;, and &lt;a href="https://scrapfly.io/docs/extraction-api/getting-started" rel="noopener noreferrer"&gt;extraction&lt;/a&gt; APIs for data collection at scale.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/anti-scraping-protection" rel="noopener noreferrer"&gt;Anti-bot protection bypass&lt;/a&gt; - scrape web pages without blocking!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/proxy" rel="noopener noreferrer"&gt;Rotating residential proxies&lt;/a&gt; - prevent IP address and geographic blocks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-rendering" rel="noopener noreferrer"&gt;JavaScript rendering&lt;/a&gt; - scrape dynamic web pages through cloud browsers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-scenario" rel="noopener noreferrer"&gt;Full browser automation&lt;/a&gt; - control browsers to scroll, input and click on objects.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/getting-started#api_param_format" rel="noopener noreferrer"&gt;Format conversion&lt;/a&gt; - scrape as HTML, JSON, Text, or Markdown.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/sdk/python" rel="noopener noreferrer"&gt;Python&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/sdk/typescript" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt; SDKs, as well as &lt;a href="https://scrapfly.io/docs/sdk/scrapy" rel="noopener noreferrer"&gt;Scrapy&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/integration/getting-started" rel="noopener noreferrer"&gt;no-code tool integrations&lt;/a&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" alt="What is HTTP 415 Error? (Unsupported Media Type)" width="876" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It takes Scrapfly several full-time engineers to maintain this system, so you don't have to!&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;HTTP 415 errors occur when the data format or media type is not supported by the server. While this error usually results from incorrect content types, it’s important to consider the possibility of blocking. With Scrapfly’s advanced scraping tools and IP rotation, you can bypass such blocks and continue scraping without interruptions.&lt;/p&gt;

</description>
      <category>http</category>
    </item>
    <item>
      <title>What is HTTP 422 Error? (Unprocessable Entity)</title>
      <dc:creator>Scrapfly</dc:creator>
      <pubDate>Thu, 24 Oct 2024 07:51:07 +0000</pubDate>
      <link>https://dev.to/scrapfly/what-is-http-422-error-unprocessable-entity-2lh8</link>
      <guid>https://dev.to/scrapfly/what-is-http-422-error-unprocessable-entity-2lh8</guid>
      <description>&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fwhat-is-http-422-error-unprocessable-entity_banner.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fwhat-is-http-422-error-unprocessable-entity_banner.svg" alt="What is HTTP 422 Error? (Unprocessable Entity)" width="1600" height="836"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;HTTP error 422 &lt;code&gt;Unprocessable Entity&lt;/code&gt; occurs when the server understands the request but finds the content syntactically correct yet semantically invalid. Essentially, the data you’re submitting may be well-formed, but something about it is incorrect or incomplete, making it impossible for the server to process.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are HTTP 422 Error Causes?
&lt;/h2&gt;

&lt;p&gt;The primary cause of a 422 error code is sending data that, while properly formatted, is invalid according to the server's expectations. This often happens with &lt;code&gt;POST&lt;/code&gt; requests when submitting &lt;strong&gt;form data, JSON, or XML that contain formatting errors&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, submitting an invalid or even a well-formed JSON document that lacks required fields or contains invalid values could trigger a 422 error.&lt;/p&gt;

&lt;p&gt;To avoid this error, it’s important to ensure that the content being sent matches the server’s requirements, such as validation rules, data types, or required fields.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Example
&lt;/h2&gt;

&lt;p&gt;To demonstrate how a server might return an HTTP 422 status code, let's build a simple &lt;a href="https://pypi.org/project/Flask/" rel="noopener noreferrer"&gt;Flask&lt;/a&gt; API with a &lt;code&gt;/submit&lt;/code&gt; endpoint that accepts &lt;code&gt;POST&lt;/code&gt; requests. This example mimics submitting data to an API and returns a 422 error when the submitted data does not meet the server's validation rules (e.g., invalid email format).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# A simple validation function to check for a valid email format
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_valid_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/submit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Check if email is provided and valid
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;is_valid_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Unprocessable Entity: Invalid email format
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid email format.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;422&lt;/span&gt;

    &lt;span class="c1"&gt;# Otherwise, process the request
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Data submitted successfully.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; __main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&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="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In the example above, we simulate a &lt;code&gt;/submit&lt;/code&gt; endpoint that accepts &lt;code&gt;POST&lt;/code&gt; requests containing JSON data. The server expects a valid email address in the request. If the email is missing or does not meet the simple validation check (containing "@" and "."), the server returns a 422 error, indicating the request is well-formed but semantically incorrect (i.e., invalid email). If the email is valid, the server processes the request and returns a success message.&lt;/p&gt;

&lt;p&gt;We can test this server with a http client like python's httpx:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;

&lt;span class="c1"&gt;# Test successful submission with a valid email
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://127.0.0.1:5000/submit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;valid@example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Successful Submission: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Test failed submission with an invalid email
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://127.0.0.1:5000/submit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;invalid-email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Failed Submission: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  422 in Web Scraping
&lt;/h2&gt;

&lt;p&gt;In web scraping 422 http code is usually encountered when an error is made in &lt;code&gt;POST&lt;/code&gt; or &lt;code&gt;PUT&lt;/code&gt; data generation. So, ensure that posted data is of valid format be it JSON, HTML or XML to avoid this error.&lt;/p&gt;

&lt;p&gt;Furthermore, as scrapers don't know exactly how the server reads the received data, it can be difficult to debug the exact cause. For this, &lt;a href="https://scrapfly.io/blog/browser-developer-tools-in-web-scraping/" rel="noopener noreferrer"&gt;Browser Developer Tools&lt;/a&gt; can be used to inspect exactly how a website formats the data like symbol escaping, indentation etc all of which can play a part in data processing. Replicating the exact behavior will decrease chances of encountering http status 422 while scraping.&lt;/p&gt;

&lt;p&gt;The 422 error could also mean that the server is blocking your requests and deliberately returning a 422 status code to signal that you are not allowed to access the resource. If you're receiving this status code on a &lt;code&gt;GET&lt;/code&gt; request, then that could be a sign of blocking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Power Up with Scrapfly
&lt;/h2&gt;

&lt;p&gt;ScrapFly provides &lt;a href="https://scrapfly.io/docs/scrape-api/getting-started" rel="noopener noreferrer"&gt;web scraping&lt;/a&gt;, &lt;a href="https://scrapfly.io/docs/screenshot-api/getting-started" rel="noopener noreferrer"&gt;screenshot&lt;/a&gt;, and &lt;a href="https://scrapfly.io/docs/extraction-api/getting-started" rel="noopener noreferrer"&gt;extraction&lt;/a&gt; APIs for data collection at scale.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/anti-scraping-protection" rel="noopener noreferrer"&gt;Anti-bot protection bypass&lt;/a&gt; - scrape web pages without blocking!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/proxy" rel="noopener noreferrer"&gt;Rotating residential proxies&lt;/a&gt; - prevent IP address and geographic blocks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-rendering" rel="noopener noreferrer"&gt;JavaScript rendering&lt;/a&gt; - scrape dynamic web pages through cloud browsers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-scenario" rel="noopener noreferrer"&gt;Full browser automation&lt;/a&gt; - control browsers to scroll, input and click on objects.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/getting-started#api_param_format" rel="noopener noreferrer"&gt;Format conversion&lt;/a&gt; - scrape as HTML, JSON, Text, or Markdown.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/sdk/python" rel="noopener noreferrer"&gt;Python&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/sdk/typescript" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt; SDKs, as well as &lt;a href="https://scrapfly.io/docs/sdk/scrapy" rel="noopener noreferrer"&gt;Scrapy&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/integration/getting-started" rel="noopener noreferrer"&gt;no-code tool integrations&lt;/a&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" alt="What is HTTP 422 Error? (Unprocessable Entity)" width="876" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It takes Scrapfly several full-time engineers to maintain this system, so you don't have to!&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;HTTP 422 errors typically result from submitting well-formed but invalid data, often in POST requests. While it's unlikely that 422 errors are used to block scrapers, it’s always best to test with rotating proxies if the issue persists. Using Scrapfly’s advanced tools, you can bypass these potential blocks and ensure your tasks continue without disruption.&lt;/p&gt;

</description>
      <category>http</category>
    </item>
    <item>
      <title>What is HTTP 409 Error? (Conflict)</title>
      <dc:creator>Scrapfly</dc:creator>
      <pubDate>Wed, 23 Oct 2024 06:49:44 +0000</pubDate>
      <link>https://dev.to/scrapfly/what-is-http-409-error-conflict-3fcm</link>
      <guid>https://dev.to/scrapfly/what-is-http-409-error-conflict-3fcm</guid>
      <description>&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fwhat-is-http-409-status-code-conflict_banner.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fwhat-is-http-409-status-code-conflict_banner.svg" alt="What is HTTP 409 Error? (Conflict)" width="1600" height="836"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When automating web tasks or scraping data, HTTP errors can disrupt your workflow, and HTTP 409 is no exception. The 409 error signals a conflict with the request you're sending, often caused by improper configuration.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explain what HTTP 409 means, common causes, and whether it could indicate blocking. We’ll also explore how Scrapfly can help you bypass this error.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is HTTP Error 409?
&lt;/h2&gt;

&lt;p&gt;409 HTTP code &lt;code&gt;Conflict&lt;/code&gt; occurs when the server detects a conflict with the current state of the resource. This often happens when you're attempting to modify data that doesn't align with the server’s expectations or the resource's current state. For example, attempting to update a resource that has been changed or deleted since your last request might trigger a 409 error.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are HTTP 409 Error Causes?
&lt;/h2&gt;

&lt;p&gt;The most common cause of a 409 error is a conflict between the request and the server’s current data. This error can arise from various scenarios, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Concurrent Updates&lt;/strong&gt; : Two requests attempting to modify the same resource simultaneously can cause a conflict.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version Mismatch&lt;/strong&gt; : If the server is expecting a specific version of a resource and the request tries to modify an outdated version, a 409 error may occur.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource State Conflicts&lt;/strong&gt; : Attempting to delete a resource that is referenced by another active resource could trigger a conflict.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To avoid 409 errors, it's important to ensure your requests are correctly configured and aligned with the server’s current state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Example
&lt;/h3&gt;

&lt;p&gt;To demonstarte how a server would return a HTTP 409 status code, let's build a simple &lt;a href="https://flask.palletsprojects.com/en/3.0.x/" rel="noopener noreferrer"&gt;Flask&lt;/a&gt; API with a &lt;code&gt;/register&lt;/code&gt; endpoint that accepts POST requests to mimic registering a new user to a database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Sample data to mimic existing resources
&lt;/span&gt;&lt;span class="n"&gt;existing_users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;john_doe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jane_smith&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/register&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;existing_users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Conflict: Username already exists
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Username already exists.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;409&lt;/span&gt;

    &lt;span class="c1"&gt;# Otherwise, proceed with registration
&lt;/span&gt;    &lt;span class="n"&gt;existing_users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User registered successfully.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; __main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&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="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In the example above, we use an in-memory list to simulate a database of existing users. The &lt;code&gt;/register&lt;/code&gt; endpoint receives the username sent by the client in the request body and checks if it already exists in the &lt;code&gt;existing_users&lt;/code&gt; list. If the username is already taken, the server returns a 409 error, indicating a conflict between the data provided by the client and the existing resources. If the username is available, it is added to the list of users.&lt;/p&gt;

&lt;p&gt;We can test this server with a http client like python's httpx:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;

&lt;span class="c1"&gt;# Test successful registration
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://127.0.0.1:5000/register&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;new_user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Successful Registration: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Test failed registration (conflict)
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://127.0.0.1:5000/register&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;john_doe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Failed Registration: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  409 in Web Scraping
&lt;/h2&gt;

&lt;p&gt;HTTP status 409 in web scraping is usually encountered when scraping &lt;code&gt;POST&lt;/code&gt; or &lt;code&gt;PUT&lt;/code&gt; method requests that create objects or update resources. For example, scraping websites with persistent sessions can yield 409 errors if the session data is outdated or conflicts with the server’s current state.&lt;/p&gt;

&lt;p&gt;The 409 error could also mean that the server is blocking your requests due to rate limiting or other restrictions and deliberitely returning a 409 status code to signal that you are not allowed to access the resource. If you're receiving this status code on &lt;code&gt;GET&lt;/code&gt; type request then that could be a sign of blocking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Power Up with Scrapfly
&lt;/h2&gt;

&lt;p&gt;ScrapFly provides &lt;a href="https://scrapfly.io/docs/scrape-api/getting-started" rel="noopener noreferrer"&gt;web scraping&lt;/a&gt;, &lt;a href="https://scrapfly.io/docs/screenshot-api/getting-started" rel="noopener noreferrer"&gt;screenshot&lt;/a&gt;, and &lt;a href="https://scrapfly.io/docs/extraction-api/getting-started" rel="noopener noreferrer"&gt;extraction&lt;/a&gt; APIs for data collection at scale.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/anti-scraping-protection" rel="noopener noreferrer"&gt;Anti-bot protection bypass&lt;/a&gt; - scrape web pages without blocking!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/proxy" rel="noopener noreferrer"&gt;Rotating residential proxies&lt;/a&gt; - prevent IP address and geographic blocks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-rendering" rel="noopener noreferrer"&gt;JavaScript rendering&lt;/a&gt; - scrape dynamic web pages through cloud browsers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/javascript-scenario" rel="noopener noreferrer"&gt;Full browser automation&lt;/a&gt; - control browsers to scroll, input and click on objects.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/scrape-api/getting-started#api_param_format" rel="noopener noreferrer"&gt;Format conversion&lt;/a&gt; - scrape as HTML, JSON, Text, or Markdown.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://scrapfly.io/docs/sdk/python" rel="noopener noreferrer"&gt;Python&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/sdk/typescript" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt; SDKs, as well as &lt;a href="https://scrapfly.io/docs/sdk/scrapy" rel="noopener noreferrer"&gt;Scrapy&lt;/a&gt; and &lt;a href="https://scrapfly.io/docs/integration/getting-started" rel="noopener noreferrer"&gt;no-code tool integrations&lt;/a&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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" 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%2Fscrapfly.io%2Fblog%2Fcontent%2Fimages%2Fcommon_scrapfly-api.svg" alt="What is HTTP 409 Error? (Conflict)" width="876" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It takes Scrapfly several full-time engineers to maintain this system, so you don't have to!&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;HTTP 409 errors are typically caused by conflicts between the request and the server’s current state, often due to concurrent modifications or outdated resource versions. While blocking is an unlikely cause of 409 errors, it’s important to test with proxies to rule out intentional blocking. Scrapfly’s automated tools, including ASP and rotating proxies, can help you bypass these issues and keep your scraping tasks on track.&lt;/p&gt;

</description>
      <category>http</category>
    </item>
  </channel>
</rss>
