<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Dad Half Dev</title>
        <link>https://paragraph.com/@dadhalfdev</link>
        <description>I'm a Dad Half Dev 👶👨‍💻 50% Parenting | 50% Python, Data Science, AI, and Web3.</description>
        <lastBuildDate>Mon, 20 Apr 2026 09:59:52 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>Dad Half Dev</title>
            <url>https://storage.googleapis.com/papyrus_images/737d94bf102ab60776c69ead1054cea3965c2e8a6fc469f93832410194d648ce.jpg</url>
            <link>https://paragraph.com/@dadhalfdev</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[How to Automate Avatar Videos with Kling AI API and Python]]></title>
            <link>https://paragraph.com/@dadhalfdev/how-to-automate-avatar-videos-with-kling-ai-api-and-python</link>
            <guid>KxiXem4u82D0Tzo4zcxk</guid>
            <pubDate>Fri, 02 Jan 2026 15:26:30 GMT</pubDate>
            <description><![CDATA[You’ve probably already noticed that Artificial Intelligence (AI) videos are taking the lead on social media. According to a Statista report, generative AI now ranks as the top consumer trend across social platforms. This growing popularity has even pushed major players like Meta and OpenAI to launch dedicated apps for creating and sharing AI-generated videos, such as Sora and Meta AI. Most users currently consume AI videos primarily for entertainment rather than for news or reliable informat...]]></description>
            <content:encoded><![CDATA[<p>You’ve probably already noticed that Artificial Intelligence (AI) videos are taking the lead on social media. According to a Statista <a target="_blank" rel="" class="dont-break-out" href="https://www.statista.com/topics/12686/social-media-and-artificial-intelligence/#topicOverview">report</a>, generative AI now ranks as the top consumer trend across social platforms.</p><p>This growing popularity has even pushed major players like Meta and OpenAI to launch dedicated apps for creating and sharing AI-generated videos, such as Sora and Meta AI.</p><p>Most users currently consume AI videos primarily for entertainment rather than for news or reliable information. In fact, the same report shows that users are generally less likely to trust content on social media when it is AI-generated.</p><p>Nonetheless, the trust in AI content may shift with the introduction of avatars, regardless of whether they are realistic or not. If the creator can validate that the information shared by the avatar is indeed correct, people will follow and support the page, even if it is not a real person talking.</p><p>In this article, I’ll guide you through two methods for creating avatar videos using <a target="_blank" rel="" class="dont-break-out" href="https://pro.klingai.com/h5-app/invitation?code=7BHHNU23DAAX">Kling AI</a>. The first method uses Kling’s Motion Control, which replicates the movements of a real person and applies them to a character or image you provide. The second method combines text, an image, a prompt, and audio to generate an avatar video.</p><p>We’ll start by generating videos directly from the platform’s console, then move on to building a workflow that automatically generates and publishes them to social media using the <a target="_blank" rel="" class="dont-break-out" href="https://pro.klingai.com/h5-app/invitation?code=7BHHNU23DAAX">Kling AI</a> API and Python.</p><hr><h3 id="h-create-your-first-avatar-video" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><strong>Create your first avatar video</strong></h3><p>You can create a free account on <a target="_blank" rel="" class="dont-break-out" href="https://pro.klingai.com/h5-app/invitation?code=7BHHNU23DAAX">Kling AI</a>, but video generation on the platform comes with a cost. New users receive a limited number of credits after registering, which are usually only enough to generate images or very short video clips.</p><p>Kling offers two main pricing options: a monthly subscription or the ability to purchase credits separately. API access is priced differently and will be discussed in a later section.</p><p>I bought a few credits some months ago, but if you’re only starting, the Standard plan has more perks than simply acquiring credits. That’s because buying credits won’t remove the watermark in your videos, and $5 only gets you 330 credits, while with the Standard plan, you will get up to 660 per month.</p><p><span data-name="warning" class="emoji" data-type="emoji">⚠</span> <strong><em>NOTE: </em></strong><em>If you’re planning on using the API instead, skip the above pricing options. Otherwise, you’ll be paying for using the platform and also for the API.</em></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/96b14c45a9ac7a98eac9bc02c0a872240c534697bb3141e40e78a9477d68d6e2.jpg" alt="" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAARCAIAAAAzPjmrAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE6klEQVR4nIWUzW8bRRjGHad24u7HzM7u7Oynd+2dGXu99u76247TJnFC0iQNbmnTltKqrcQBCSGEQAgJASeO/An8IVxQDyBEVD6KKiRQJYSgCNFLJQTiFmSbQ0uFeDSXGf3eeeYZzbwZUlOgI2lIVxBCSDVNK7+0lHtK2YWF7EI2l8stLCxkZppP/1eZfCGfL+QWs4v/pVwul8/ndV3HhppfyruumyQJDxkxSDb777ITi4v5XO7xlcyUeQzLzvQ4kc1OT6qqqkZQfinnum4cxzzkTxtkFxczmWm+JwyWCwVJBqIIBEGCUFFVHUBFkuF8URQk03R04iKVYN0mhq1hSxDlwrIAoCaIkiAqc1IW5aisbbaLF7dqLUaaFLcYicp6plA4KQNNBkgQJdtxRqNREND80kkZIBkgSYa8EjWSDuM1y/Yt2y96zDQd0/HTVt8vsYIgSTKUAYIQDiPnpcuj91+/NKha7UDrVYwON/4xAFArCCKlfHfvbK+/wljFtF0FYUGU47R75fkbk3OH/cGpMEo9n2PdDCjb2z/YP3suitNywBWVyDIYNfnNK5Prhwd76+2NXq0TOvUnE8iW7YZR6nqBphuSjE7klwuCxHi11x/xSq0ccNcLsG6r2DBNO4oT23F1YqhYzy0VRFFMK97mqNuPeIM6DeqULchskBEEUVF1pOqCIDHGtp/ZGg4HcRynadrr9QzDDOvt/fNXN7YnvdF4uLq5Nt71S9zz+Xh8sLIyjuq9RtJvdkaW7far9vW97sWtxk6/dGaFHaw1OqGTwToJKHe98olc4e03X35w/+iLzz6699Un33z56V9/Ppoc7N965b17D48//vrno+8efv7tg9+Pjw+v3Xzh6qv3vz++ffuHo6Nfj45+fPTo+OKlF984jI/vvvvT7bd+u/PBL3c+PP7j7juv3coAoNhO0TRtGSDbduI4qdfjVqsTx2kjaerECFjYGW50Busrp7a6w7WV1bHnU2LYtXo7ilppaxjF7UbSMQ2Le3jUpsOErvXjUTda7TYqgZUxTStt9SivKghDqFmWo2KiYl1BGEANQMVxy5VqQllY9Oh8EMNVkOq4nmlaSJ2RSEMQ2QSxosGKxCXIwYqNoaUrGVkG02dn2ssFkTE+mUy2d3Z2dna3t8+krQ7GpNZoHl698dzhtcn5y+cvXNnY3HXcsl9ik3OHe/uT7Z29M7v7/cEqIQYP3AtnNy48O97bXj+7O14bDcuOkZEB9HzquJ6CsIpJWI/rSTOKm42kzSuhionn0/7g1GDl9HB0ejha7/ZXHbeMVL1WbzSSZiOZ3mRYqxNCTKzVa7UkjtPZqNdqnkUyjFW6vRW/xADUEMK+Tz2f+iU2fbgykAFyvSCM0jBKa/WW7ZQs2yeGjVTd8wO/NCVnX1qGUDGxVnbdwPOo72MgKYVlgkCmVCrbTnHWGyBSdcarjIeMV23HBwhLMix6NE57aasfp71KtVH0qE4cpOqUVRgPKQunJMQAQBMrNAiqnFco8xwHA6ArciaXX5JkCKAmimBWVuWVmucHOrEA1GQZul4Qp71WexBGaUArcwMF6QHlM5LOSAwgNLDC6NQg8HyL6JosTw0KgjjdCKC5QUA546HjlrFuTNvRLEEj6cRpL6zFfok7bjBPEFBGWXX2t6fk/IpYucwCWnZdU8dIkggCfwNBc+2xG3To1gAAAABJRU5ErkJggg==" nextheight="597" nextwidth="1100" class="image-node embed"><figcaption htmlattributes="[object Object]" class=""><a target="_blank" rel="" class="dont-break-out" href="https://pro.klingai.com/h5-app/invitation?code=7BHHNU23DAAX"><u>Kling AI platform</u></a> pricing plans</figcaption></figure><p>Before picking a pricing plan, you can see if you have enough credits to make your first experiment with the <strong>Motion Control </strong>model under the <strong>AI Video Generator</strong> tab.</p><p>This option lets you upload a reference video along with an image, which <a target="_blank" rel="" class="dont-break-out" href="https://pro.klingai.com/h5-app/invitation?code=7BHHNU23DAAX">Kling AI</a> uses to replicate the video’s movements and expressions. The number of credits required depends on the length of the reference video. Make sure you start with a short clip.</p><p>In addition, you must provide a prompt that supplies contextual and behavioral guidance for the output. You can make your avatar more extroverted and smiley or more serious, depending on how you structured your prompt.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b7e40fdd8f92b328800b6c39364f8f73ac9547dbddaefa96e9a9bdddeb9163cb.jpg" alt="" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGCElEQVR4nF1UW0wc1xke78wwM5rD3HbuM8zO7JVdsgvscl1YE3CKAeM1t4KtYKUPrfrUSH3pU16qKHmpkocoVRTFzsW3SsTYFqZuCBdjzMWx6xQQaO0lYAwhjuN0rYYW41hkol2IGuXTp6Oj8x/p0//p/z9IVjRBlFXN8PoCbo/P4/UXGJYvEAwEi1TNUDVD002a4WlG8PmCkUgsGquM19TFYlXlFfGKitrS8vKCsEtRXJpm/YKKaiqKAdG0k6I5XshqqJruclmyokmSomoGL0iCKEuSwvIiTgIlB4ZhCYJkGJYkSZpmUDRPEmWO4xAERdE8NIs8BEEJgnC5TNM0Iack0jzPC7KkaBjJAMrJi4ooyn5/wOcvZDgRAHqXFEXRORAEQZIkjuMkSSIwnA9IkiRh2IEgMLIHGEURiqIAAJBQIAuajBP5HMu21lc07q/yWibLia1d3e09Pclka2tnd31TM6BoAADH8RzHS5KsqKqm67KiyIZHMHySqqmqpqiapuuarquqhuM4nAPkdIosI+AUF3Ibn53+09LEqZdfOlLgCa7t2KsP761Pvb32v+/++eUDQZQKXFZV7fOlZZV/fuOtqaV7w3MLIwtf3Ji8MjvwxsTtmyPz6bH5O8Ozi1NL9948caqssqY68bw3EIRcbks3DBSnouHCgVe7z/6xrbuxwvQ/t/Tfp/OrX3w69OHK1vbknWVelHyFoaZkV31jy8n+gYe2vbJtr25uPRx6ZbXv98vXT6/v2Gvb9sqTHx7Z9sejE40tyaZkZ0msCvJF/O5CD4ZRJaHAuy83/aEuUF3o8kfKUo/+Pbcwc/vW8N1H3352f4MXxUBR8eGuowdb297ru3R/205vfj//1cNPLr6d+Wrq8vm/Ln7zn+XNZ6nM1vozu+/T8db27mTXsVhlHJLl7JgCivO63YdqfPUhzaVIwXDJxMTFC/2n+s+fGx+/OD4x4OT5ouJox9Hewx3d7/cPrm7bdzJbqcdPFxevbaQuTc4MpjJb6cfbdzJb97+3+4avdfT0dhx7qaKmFmJYHlCsqulef1BVFEPXFVWjac5tWabl1nTTsixNVVAULY6Vdxw9fqSr54OLl1e37buZJ8tP7KGJ0ddf+W3/J4PL23b68VYqJ9A/Otl59HjXi7+prElAkqQIoozjBE3TJAlIkA9APqBoggAYTmAYjqB5+/Y5ECQr0N7Tm+zs/KD/8saOvfhN5ubC3L8+H1tPDS3MX5ue+zyV+W5p8+mDHfvC1cmOnt6uY8f3OqAZHlD07ggyLMeyHMOwbG4cLctyu900zcAwEo6WHfl1T8vh5Mn+gbVn9sytmZnrV2Zmrt6+NX7zxtjk+OCNudn05s7K1g9n/zGa7Oxu6z5WXlUDOZ2CkxcJgqRAdpNIEvC8YJomAPkomre7WRiGISjqCxYdaG5J1De8c/pvdzOPp6ZHhkcGJieHpqdHpqaHx8b+Pnp1eHZ9I/Vt5uzglReaDx1sbSuOle9ZhKJ5MJzdQxiGURTFMQyGYYfDsS+HXAkNR0rb2jsbXmg+8c5ra+mhC+c/PHvm3XPnTvb1fdTXd/rMmfeuXHo/PTvwYGX0oxN/qapJNDa3BMMRiKRoQLE4QSJoNk72mA2WXeShaB6GYSiKewKBynhtNFZVV1d3sPFX9TlUV9fG47XxeCIer21oqDvYeKD1UHNi/35vIFQYKnaZbsjrL7LcPpwEFMP9nIBmdi8kwwCaIQgAaJrlBadTJAGLoASGAxTLx4n/E8HyCZIFlJNmBJbLkqY5yBvymR4vDlMAdRIOinBQOEwRCA0wJwHT2ReE4UgJkGzWqJxvu1mW6++ncEP2+s/FjyP7KWsv5HDsg2RN5nkhUO8r74lY9ZrVoJl1mpnQo21hf5PHPKCFkoHE76r1kC4Kkt/vtyxLUVVdckaKAj5/wLIsr9drWe5wOGwYhsPh+EkWNs1CTTMhmuFJnE2cCXV8HT2Sjravlh2aLW2+Xtw0FUmmo20rsWS6pH2j1Ner5iOsqqmKosiyIkmSYbgURVUUVVVVWZZVTZPlXCl3CoLg9pTQtPAj8jXciEm0AigAAAAASUVORK5CYII=" nextheight="604" nextwidth="1100" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Create an avatar with Motion Control on <a target="_blank" rel="" class="dont-break-out" href="https://pro.klingai.com/h5-app/invitation?code=7BHHNU23DAAX"><u>Kling AI</u></a></figcaption></figure><p>Here’s an example with an image I created using Nano Banana Pro on Gemini:</p><div data-type="embedly" src="https://vimeo.com/1150418807?fl=ip&amp;fe=ec" data="{&quot;provider_url&quot;:&quot;https://vimeo.com/&quot;,&quot;description&quot;:&quot;This is \&quot;Kling Motion Control - Dad Half Dev\&quot; by Marco Rodrigues on Vimeo, the home for high quality videos and the people who love them.&quot;,&quot;title&quot;:&quot;Kling Motion Control - Dad Half Dev&quot;,&quot;author_name&quot;:&quot;Marco Rodrigues&quot;,&quot;height&quot;:864,&quot;thumbnail_width&quot;:960,&quot;width&quot;:1056,&quot;html&quot;:&quot;&lt;iframe loading=\&quot;lazy\&quot; class=\&quot;embedly-embed\&quot; src=\&quot;//cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fplayer.vimeo.com%2Fvideo%2F1150418807%3Fapp_id%3D122963&amp;dntp=1&amp;display_name=Vimeo&amp;url=https%3A%2F%2Fvimeo.com%2F1150418807&amp;image=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F2101290478-c7ce8fe075a67d581dcecd7f8e40506af3b4880e90368b1bbb2804df29d22eee-d_960%3Fregion%3Dus&amp;type=text%2Fhtml&amp;schema=vimeo\&quot; width=\&quot;1056\&quot; height=\&quot;864\&quot; scrolling=\&quot;no\&quot; title=\&quot;Vimeo embed\&quot; frameborder=\&quot;0\&quot; allow=\&quot;autoplay; fullscreen; encrypted-media; picture-in-picture;\&quot; allowfullscreen=\&quot;true\&quot;&gt;&lt;/iframe&gt;&quot;,&quot;author_url&quot;:&quot;https://vimeo.com/user203866235&quot;,&quot;version&quot;:&quot;1.0&quot;,&quot;provider_name&quot;:&quot;Vimeo&quot;,&quot;thumbnail_url&quot;:&quot;https://storage.googleapis.com/papyrus_images/a12e93b3e8d9e0b7b263a56c2e9c8fc8378fcf666babf8ebd9d19eba72f6b232.jpg&quot;,&quot;type&quot;:&quot;video&quot;,&quot;thumbnail_height&quot;:785,&quot;image&quot;:{&quot;base64&quot;:&quot;data:image/png;base64,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&quot;,&quot;img&quot;:{&quot;width&quot;:960,&quot;height&quot;:785,&quot;src&quot;:&quot;https://storage.googleapis.com/papyrus_images/a12e93b3e8d9e0b7b263a56c2e9c8fc8378fcf666babf8ebd9d19eba72f6b232.jpg&quot;}}}" format="iframe"><link rel="preload" as="image" href="https://storage.googleapis.com/papyrus_images/a12e93b3e8d9e0b7b263a56c2e9c8fc8378fcf666babf8ebd9d19eba72f6b232.jpg"><div class="react-component embed my-5" data-drag-handle="true" data-node-view-wrapper="" style="white-space:normal"><a class="link-embed-link" href="https://vimeo.com/1150418807?fl=ip&amp;fe=ec" target="_blank" rel="noreferrer"><div class="link-embed"><div class="flex-1"><div><h2>Kling Motion Control - Dad Half Dev</h2><p>This is "Kling Motion Control - Dad Half Dev" by Marco Rodrigues on Vimeo, the home for high quality videos and the people who love them.</p></div><span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-link h-3 w-3 my-auto inline mr-1"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>https://vimeo.com/</span></div><img src="https://storage.googleapis.com/papyrus_images/a12e93b3e8d9e0b7b263a56c2e9c8fc8378fcf666babf8ebd9d19eba72f6b232.jpg"></div></a></div></div><p>The <strong>Motion Control </strong>requires you to record yourself or have a video reference. The other approach is to create an avatar that, instead of taking a reference video, takes a text, an audio, an image, and a prompt. On <a target="_blank" rel="" class="dont-break-out" href="https://pro.klingai.com/h5-app/invitation?code=7BHHNU23DAAX">Kling AI</a>, you can do this by selecting <strong>Video</strong> and then <strong>Avatar.</strong></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a2588471610831ba7bcefac8f6bf68fe2e35d5a0d8547fa5d3273b72cebd958f.jpg" alt="" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFW0lEQVR4nI2Va0xTZxjHj0mvQHtOz/1Gz63nnFItbnIrtOAEZFAuLYgQpAMUKBQUBBQkYwiIoFPX6dTNzKgZyVCXzekmkxkvw2Ec0QxJtqgxc9l0xmTZt33YssTFVojRZfGfX06e9/3w/N//+ybPASiaJQjKyol2h5NhOTNoASH0RUxmSBAEWZYVRcFxXKvV6l9OAAzjEISRFGO1CiiGQxYMRoj/MgCJiEiKwjDsJbsbDAaAoCkLhqlqQprLrSaqBEUxrPCiQZwJVFWV53kQgiiaiTHG6HS6/++u0+ni4uIAgqNxhmRYkZdVVXVwvI3jJRR7GsIMWlCMsHKSGbSwLAuCoC4iwzMyzstgMDx3/EgCgo41Qc111V2NNZykiJIsSjIvyBxvEyWZYTkYwTGcMoMQSZImk0kfObhWq9VotFqdTqPVLlq0CJjX01CRF9JotBqNBmBYzmTBmwOVHWsrRJvicrk9nsyU1DRBtNkdzpTUdFe6x7HECSM4jmEgBGl1uhijEUVhkkRQcwyKwAIv2O12h8MhimKM0ag3GGIgi8FoRBAYwzGApuNJijFbcASjOd7GC0oEOd4qRZZydAkjKIrEFnkSq/JdJAa2NZWFW0umwxu21JdMTE7emb3+6w83z1+6nK+qatZrcns7KturK1d1tTcDSqJdUCSaEWw2+3x3heOfFnwEQVRgBJd44lhvw5nRjTxHDnfXTb659udjO3atL52+NnPx4/cnDu36dmpqmVUq9qS+HiiPT00pLVq5uysIMBxHMgxFWwVxobucnJLhWPKqlVsIpGAYvjVYOd4XPNwR4AW6N7Rqcqh5rK30rUDmdzPXD+x7d1NH19TUpXD3upHNG3bvHBzc3FhT7l3tXgwQJIPhJEmxUQOOl2XFkebKTEpO5/jo/TwBRIgPt/d88V7/mf1D7Z2bdtR6w9W5fZWuseHgZ8ePjWwbaKyt3b9r68GQP7y9v7VxXV+w6u3ejXX5HgBBcRhBn0ugqE5JSlgwEAQVhLCaMl8wFMrz5quyVJ2TUfFaSk56YlXxCl+uK8uVVLg82ZvhsMfTNkVR+Phku1xVkluU7QYwnEQx4lmDheJZYBiv9af1ezOOtpQM1mdW58iHtpTPzFw9efrs+ckLc1euXZ2+MTb+qccpB4tXjB/eu2d0aOLs2Xt3bwMkxRAEhaAEQbAoRkaJuEYLiqRYkmJNFqwnWDjiTTrVlLMnkD3c39xZltpUVvj5V6dnb8zdvPPwx4d/Xp6eqcvLOD3UceXrU+NjR89PfPnJ8eNAdJCxnEgyrMkMmkFoAZMZRFCMFyRBtIGgpWnjGye3d80d2LZ7uK3M7+0sz+tubysuLjr3zY3p2Uf3H/01e3NuS6jxRHjHTw/+ODJ2cufo6PqWDiAhYalNthtjTTBCwMiTYQdZ8AhPCpMZ1hvjDAaTEYQ66/3nPtg2uW9gsKGyq21dY33AX+Lr7uy6/9vDCyd+f3D78a27t65c/f7vfx7/cu/RqY+OHB3qvTd9CbA5ZEGy6fWxOn1MFL0hbuGrmyfODBYuT87zpObmeDwpizkrnZmWYrdJbk/W3n0HGmoGe3t2Dg0ONJQW1FRUrvHmtvrzAr7iWl8BwHAMSdORgUMSBBUZ1ziKEWbQsrCJYgRkwdKSlATBlO3E3W4yJyNra2vNO+sr3E65JI3fP9J3ODyyasXS+qKlNdmvVBQX+Hz5ouhw2BMAEMLMoCXeKsiKnRckgqBIipFsCoLi0R+RKCkMK2AoluiwpScr5cuV1d7krPT04frCiwMNbT7PyiR6KOTvafavyVnSUpl3sCMQ3hwKtoSWLfMUJDn/BWCBe8SN378XAAAAAElFTkSuQmCC" nextheight="602" nextwidth="1100" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Avatar 2.0 on Kling AI console</figcaption></figure><p>On the console, you’ll find several avatar examples ready to be used, but that’s not as fun as creating your own!</p><p>The steps are similar to <strong>Motion Control</strong>, but you need to add the speech (text) and an audio. The longer the speech, the more credits will be consumed. Instead of the text, you can also upload an audio file.</p><p>In the next section, we will use the <strong>Avatar 2.0 </strong>to automatically create informative videos based on summaries from articles. For that, we will need the <a target="_blank" rel="" class="dont-break-out" href="https://app.klingai.com/global/dev/document-api/quickStart/userManual">Kling AI API</a> and the Python programming language.</p><hr><h3 id="h-create-an-authentication-token-for-the-kling-ai-api" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><strong>Create an authentication token for the Kling AI API</strong></h3><p>You can use the same Kling account to access the <a target="_blank" rel="" class="dont-break-out" href="https://klingai.com/global/dev">API console</a>.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/390c3ccb64a1b8d1413cbc00ea10252e12bf83c6ba3fbc90ec5381ec74ba5dd9.jpg" alt="" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAARCAIAAAAzPjmrAAAACXBIWXMAAAsTAAALEwEAmpwYAAAD50lEQVR4nG2U227bRhCGaYqmQLp2LEeuSOpoitwjD+JJFCVKokhLVhIEDdoCTdoGDlDYbe961dsCQfsMfYE+Ux+ltymWtC0ryWCwGAx/7rczsyQny3K9XpckSRRFnuc5jms2m221o5yr6nlbU9ttrdNWOx21o7W6bbWtKZr6paa12r12r6N1lKamKVq73dZUTVNZ0O12FUWp1Wp8aVyr1VIUxTCM8/NzjuMOuAN9qK9uk9VtvLyO5j9E87fh/Mcwu40X78bz11F2m8yvo+yXeHkdr66T/DZJXgUU03AWJKvYtmzbtjHGgiBwHMcAtVqtinier7C6rk8WUbjwooUfzgLmqRemwTgPojRIVpPxMoxW4TiLJlnozV0roBiT0djN8mWWZa7rQggFQbir4MnTJ03tabN11mg0zs7O6vW6ruub9SZf5ZfFZrvZPts+y1f51eYqz4oiv7wsLjfFZrveFvllGAUEE4IIIcS27KIo1pv1ZDIBAOwAh4eHYl0UBEGosYXn+cFg4E8dN7Yqd8a2HVBnbLsTFgfpaJS41MaOY/nhyLYppZhSTAiJ4zjLMs9zEHpUgSiKsnwkSVLVH47jut0eRBgABOBnHGPCnkIE2eEJAPDBTROYJgAAGYa5V0G9Xpdl+T510FLU/mDY6+u9vt69D0ofdnsD2/XjSRqE8b1mpyzFbO10L3a3qGyMUI26MkXRACQAYgCxaSIAygAgw4QAYogIwhRh+jh5J2ZFs6DX13cASZaPSzs6Ojo+PuZ5XlFUTCyELctxw/GYOi4mFkQMialT7Y4wLTUMg4mFiWXbI8fxWZLY/cEjgCzLJycnp6enjUZDkqSqAkQdAHG6Wv7195/pag4hOzVEBBJqOaObm1/TeVaVwpKIxJP0j/fvX379FQDsEHsA4ZFVQ1YUrTqy4/vffP+t7fsI3W0EEfGi8LubN9EsqahV0zwvuv7p3WK7ZABi7QH4fXsAUNsdx7MsW0fR1HJGVYssZ5QXmywv8mLj+VGV9IO42FylaXZ19SKdZ9R292bwWQDC1POj6WyZTOfT2bLci00vCCfT2aL0ZZykVQXhOEnTjIlni2S6cLxgD1Bjdtei6i5VFTwME5XzrC4JJBRiAgmBmDANpKaJMf5YvNei6lcqyfLR0ReHolgCVMOEQwM8uAkQtV3quASNsOli4GLgAIzgCCEfmQgOh+ZOb8Jef7ADiKLIAJJ036QDRVEvdKM/GD74hW4wpA7pworeeOErd/zac5/TgWFcQLOn75Ts69ONbu8RQBCEw9LKXrFs6xMAe204bB33XvyT/P7h5c//rX/78Pztv3lX0z+SfQr4H5yg2uvmH+LyAAAAAElFTkSuQmCC" nextheight="582" nextwidth="1100" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Kling AI <a target="_blank" rel="" class="dont-break-out" href="https://klingai.com/global/dev"><u>API platform</u></a></figcaption></figure><p>The pricing plans for the API usage are different than the ones previously discussed. In our case, we’re going to use the pricing that is visible under the <strong>Functional Models, </strong>which includes the <strong>Avatar</strong>, <strong>Lyp-Sync,</strong> and other products.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f215a4dfde1a637fe9a9b7dd3825768b5f959e7dbb1cec170c0fd07f2f1a2906.jpg" alt="" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAsTAAALEwEAmpwYAAADhklEQVR4nJ1T30/bVhS+Wq/kB1eWNdcyyLOQvMiTW0ciGSRNgrqVLslYhJB4ZQ+tlFYOyoxilNvWg4T8GKQKqA1aAiQMtzLIXQgi1WA/yrS98A/wzCv/B1NyJS9UYx37dHR1z/Gn8917vmsQiURyudzU1BQAYGBgwOfzMQxD03QwGKQoimVZWZYJggAAkCQJIQQA4JWmaVy/DMFgUFXVzg52cRmP47izs7Pj4+O9vb3T09Ojo6Pz8/O1tbWTk5PJyUlH78qAENJdUF3wPN/f38+yLMdxgiDwPM+yLISQJEmapv+PBkmSkiTJsiwIAoRQEARFUXA7SZIGuiAIQhAEWZYpirpad5fLpSiKLMuiKOJUEARRFCGE2BWWZQmCUBTF5XIBAERRlGX5P90D+/EOVVGUr7qIRCIQQp7nsbbjee/mg2vXrjotQNN0X1/fR3wHAACCICiKIknyCi1I8vqQLzDkC4yGo7HxiehYDKdD3QhHxu7cvXfzlvvmLbc/EIqOxUbD0S8iX8bGJ0bDUcyJjsVi4xOx8Ql/IOQPhDiu74IAw9yYNTIz6OmGud1680tz/2DWyDjx5tffW+3DtJFJIWNhqdw+fNvcP2i1D3/67Y9Ny55BTx9n86/sVnP/4Oe3f84VFucLz1zSJxde8IcMo2q6qun3H07nS+VH38zgVNX0eELLFUtP5nLxhOZw4gktbWS+fvDo/sNpp1htmJg/a2TEjzvm/+2HI5DUkaajpI4cAVXTF5dfZItL+CteU8jIFpeSPcykjlZWaylkvEdA1fT1LevJ3AI+b6XWeGk3Teu1Ze+a1utKreG0M7L53kNMz6Q3LTttzF8qgI+TQkbD3Ck+e467JLtRN626aTlpUkdpI1MoLfdykjpa37LSRkbV9MfZPBb4Bw9SyPi+bs4vfOdMPJ7QypW1cqXqVDDt24VC7w1UTV9ZrWk6+rcRYet2dtsrq7V4QosntHypXDetasNc3+qs2eISlkkhI1cs9Urieb7HA/xgWu3D59XOrOMJrbRS2dndr5vWpmVb9l6+VHYECqXldwTWt6xLBRjmRgoZ+OI/WD8uLr/AYy1Xqq/s1oa5vWFuv7SbuI5pzt4J/DqSOporLLok6YIHJHl90Pup2+Md9A53fs7bQbfH6/Z4/SMjo+Honbv3Pu+GPxDCdc+w3+E4ERr5bNA7rHi8Q8O3OY7Drf8CrUOz2EFAAekAAAAASUVORK5CYII=" nextheight="623" nextwidth="1100" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Functional models product prices</figcaption></figure><p>These are the available pricing packages:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/0584c6dcaf67dab3559c33415dac3e457ef26a6ef0599595bc8ebf7d78ab2ee2.jpg" alt="" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAsTAAALEwEAmpwYAAADaElEQVR4nIWU4WvbRhjGhUGEgJEI8WT5zqqiep6j1nPRqqj1Jt/sarGV3LyJHuqulsVMXUPW1JAhIrQvIR/6IVtY2B+wbyFfts/788aG71bhZHH6wxzi8Yseve/dc4JpmmEYQghFUazX64qiFIvFer0uSZKqqoqiCIKg63qWZQcHB0EQRFGUpunZ2Znv+4IgrC0hvqdQKAiCIMsyQkgQRXF9fZ1LfBUEoVgslsvlUqmkMBqNhq7rBgNCyFdd1zVN29zc5GUbGxvCdQqFgiRJ1yRJkkrXURRFluVSqQQhVBkAAAghAKBcLvN67rFM/qE3aTQaWfZTHMcIIY/h+36r1dI0LU3T6fQ1QqjH8DzPsiwI4XFyHI9jruSsra3dfDX3NE3z/PycENJut11Gr9czTVPTtIuLiyzLuOi6LkKo1Wqpqvrrbxfvfn6X17cZoije3oGu6wih5dIeM4AQIoTaS3ADAMCXftcddNzOoj63v6UDjmEYs9ksjmNCCKWUEBIEQbPZBABMGSGD65ZlqaoaknD8coTxvu/7g/4ChNDKDgzDCMMwjmOMse/7vNpkHRBC4jgOggBjzHU+IkrpfD6PGZRSjHGv17trROwj+nyv+LPJDG7ofPMBAHx7Xdd1HCcf4MoR6boeBMF0Op29JwxDboAxnkwm+V+UUm7AXbklXz3PW9lBrVajlIZhSOnLKBqHYTiio0efPoIQ/l+3P7MBAHwys9ksy7IoivgYVxrIsqwuU1a12j3wcVWW5EqlAgDI9eqWVv3kniRJcBG7/9AZAICVQdM0zfd927Yty3psP97eavz4R3L19+/KRwrGeMfZsSzLduztrcb3v7z6658/K7Cy+9Vuvz/AGDuOY5pms9m0LOuWDvKgXV1evT18u2PvdFHXdd19jG3H1jTt8vLyODl++uQp1we+/+SLzwEAaZqenJycnp4mScIvxLs2+X7t/otXdDgO+s8Hey9w51m3i7rbje2qVv3u9eib0bdM/7rzrJsHDS8xHA4xxh8I2t7+3m5/1+24ix+7Kh48fAAh5Poi50zPDQ4PD4+OjpIkSdM0SZL5fH7XKTIM44ARRdF4vDgthJA8yW9+eDOZTPix4UkGAESMOI7zhw8ELQgCQojnefzWzJM8HA4JIfzUc513wG+t5ZTdGNG/qnc2M2rtYakAAAAASUVORK5CYII=" nextheight="631" nextwidth="1100" class="image-node embed"><figcaption htmlattributes="[object Object]" class=""><a target="_blank" rel="" class="dont-break-out" href="https://klingai.com/global/dev/pricing"><u>Resource packages</u></a> for Kling AI API</figcaption></figure><p>Once you’ve picked your preferred package, you can create an API key, which has an <strong>Access Key </strong>and a <strong>Secret Key.</strong></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/365168cbb50d729d15626ab09496e34389d01f861606534ad3f75cdad96bff29.jpg" alt="" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAJCAIAAADcu7ldAAAACXBIWXMAAAsTAAALEwEAmpwYAAACE0lEQVR4nK2Sv2/UMBTHUxJd09CLf8Q5O/E5cZw48fl+tg2txIHUESF1QGJgQwxI8AcgsYBU0QEGZgY6gAAJwcT/wf9UdDn16NANPnrD118/vyc/PYdSygXPsgxC6Lqu53kY4ziOXdfdWnHDvWTrkmt1EASEkF1/l9nB8tns6Mnk9tPZ/EHjWGvbtj05OeGcO47juq5SZdu2hESEEAQhIRGEEACAV6C1jzHuxOoq7o5CCDsd5Uzef3H3x8W784vXXy/OXv5+7IQgxAMEMYQQEUK6H0RKlVKWVVVJqbSu67pRqtKV7pxSiDzPiyyTK1Mbaydam1wWQuSNsYWoUiwypoasuOn1naKW7Z2D2f7UWmuM8X2fxGxk5ykv1lGoxo4Xi4Ojw+Xx4fJ4cWupR4tmvFeZ6VCoupnUzWSdmUtdj+aT+f4wU42ZGDtLuHB8f2c3CD3X28wUAKTrUUQoIhThAUs4Iezew0fvv/86/fDpzfm3049f3n7++fzVWURYWeqyHmljScx4ls329kOAEB7kUhWqHgyYAyHMskxKGQSBt8Lt98OUCwgjADGAOCI0SQVjKcbRds/3/Z3tnr/d83f8AECcJDzlw5QLhOKY0lwWIUAAYsqSJOEIR04QBACAfj9cr0rXw9sI7wq93qr+1Vhn/n3YjWFTYW06GOM0TUkcd4tBri39LziUUq21MWY8HlNK/3uDPxVUUHaipYwEAAAAAElFTkSuQmCC" nextheight="319" nextwidth="1100" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Create an API key for the Kling AI API</figcaption></figure><p>Now, you still won’t be able to make an API request with the two, you must do a JWT verification. Here’s the Python script:</p><pre data-type="codeBlock" text="import time
import jwt

access_key = “AP4...” # fill access key
secret_key = “adJme...” # fill secret key

def encode_jwt_token(ak, sk):
    headers = {
        “alg”: “HS256”,
        “typ”: “JWT”
    }
    payload = {
        “iss”: access_key,
        “exp”: int(time.time()) + 1800, # The valid time, in this example, represents the current time+1800s(30min)
        “nbf”: int(time.time()) - 5 # The time when it starts to take effect, in this example, represents the current time minus 5s
    }
    token = jwt.encode(payload, secret_key, headers=headers)
    return token

authorization = encode_jwt_token(access_key, secret_key)
print(authorization) # Printing the generated the authentication token"><code>import time
import jwt

<span class="hljs-attr">access_key</span> = “AP4...” <span class="hljs-comment"># fill access key</span>
<span class="hljs-attr">secret_key</span> = “adJme...” <span class="hljs-comment"># fill secret key</span>

def encode_jwt_token(ak, sk):
    <span class="hljs-attr">headers</span> = {
        “alg”: “HS256”,
        “typ”: “JWT”
    }
    <span class="hljs-attr">payload</span> = {
        “iss”: access_key,
        “exp”: int(time.time()) + 1800, <span class="hljs-comment"># The valid time, in this example, represents the current time+1800s(30min)</span>
        “nbf”: int(time.time()) - 5 <span class="hljs-comment"># The time when it starts to take effect, in this example, represents the current time minus 5s</span>
    }
    <span class="hljs-attr">token</span> = jwt.encode(payload, secret_key, headers=headers)
    return token

<span class="hljs-attr">authorization</span> = encode_jwt_token(access_key, secret_key)
print(authorization) <span class="hljs-comment"># Printing the generated the authentication token</span></code></pre><p>You can tweak the script to increase the expiration time. The output is a Bearer token that will be used for the API requests.</p><p>You can learn more about this and the following steps by reading the official API documentation <a target="_blank" rel="" class="dont-break-out" href="https://app.klingai.com/global/dev/document-api/quickStart/userManual">here</a>.</p><hr><h3 id="h-create-the-audio-and-the-avatar-with-the-kling-ai-api" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><strong>Create the audio and the avatar with the Kling AI API</strong></h3><p>Unlike the platform interface, where an avatar video can be created in just a few steps, using the API requires a multi-step workflow. You must first generate an authentication token (as explained earlier), then create the audio file, generate the video, and finally retrieve the video URL.</p><p>Let’s start by creating the audio file. In this case, we will choose a Voice ID from the <a target="_blank" rel="" class="dont-break-out" href="https://docs.qingque.cn/s/home/eZQDvafJ4vXQkP8T9ZPvmye8S?identityId=2E1MlYrrPk4">spreadsheet</a> provided by Kling AI.</p><pre data-type="codeBlock" text="import requests

AUDIO_URL = “https://api-singapore.klingai.com/v1/audio/tts”
API_TOKEN = “eyJhbGciOiJIUzI1Ni...”


headers = {
    “Authorization”: f”Bearer {API_TOKEN}”,
    “Content-Type”: “application/json”
}
payload = {
    “text”: (
        “Forget small steps—Ethereum is preparing for a massive leap. “
        “By 2026, the network is set to start scaling exponentially “
        “thanks to Zero-Knowledge (ZK) technology. Think of it as a total “
        “brain transplant for the blockchain, “
        “similar in scale to ‘The Merge’.”
        “Instead of every validator re-doing every single transaction, “
        “they’ll soon just verify tiny ZK-proofs. “
        “This shift could eventually skyrocket Ethereum from 30 “
        “transactions per second to a staggering 10,000. “
        “The best part? It’s so efficient you could theoretically “
        “run a node on a smartphone. While it’s a multi-year journey, “
        “2026 is when the real speed revolution begins.”),
    “voice_id”: “chat_0407_5-1”,
    “voice_language”: “en”,
    “voice_speed”: 1.2,

}

response = requests.post(AUDIO_URL, headers=headers, json=payload)
print(response.json())"><code><span class="hljs-keyword">import</span> <span class="hljs-title">requests</span>

<span class="hljs-title">AUDIO_URL</span> <span class="hljs-operator">=</span> “<span class="hljs-title">https</span>:<span class="hljs-comment">//api-singapore.klingai.com/v1/audio/tts”</span>
<span class="hljs-title">API_TOKEN</span> <span class="hljs-operator">=</span> “<span class="hljs-title">eyJhbGciOiJIUzI1Ni</span>...”


<span class="hljs-title">headers</span> <span class="hljs-operator">=</span> {
    “<span class="hljs-title">Authorization</span>”: <span class="hljs-title">f</span>”<span class="hljs-title">Bearer</span> {<span class="hljs-title">API_TOKEN</span>}”,
    “<span class="hljs-title">Content</span><span class="hljs-operator">-</span><span class="hljs-title">Type</span>”: “<span class="hljs-title">application</span><span class="hljs-operator">/</span><span class="hljs-title">json</span>”
}
<span class="hljs-title">payload</span> <span class="hljs-operator">=</span> {
    “<span class="hljs-title">text</span>”: (
        “<span class="hljs-title">Forget</span> <span class="hljs-title">small</span> <span class="hljs-title">steps</span>—<span class="hljs-title">Ethereum</span> <span class="hljs-title"><span class="hljs-keyword">is</span></span> <span class="hljs-title">preparing</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title">a</span> <span class="hljs-title">massive</span> <span class="hljs-title">leap</span>. “
        “<span class="hljs-title">By</span> 2026, <span class="hljs-title">the</span> <span class="hljs-title">network</span> <span class="hljs-title"><span class="hljs-keyword">is</span></span> <span class="hljs-title">set</span> <span class="hljs-title">to</span> <span class="hljs-title">start</span> <span class="hljs-title">scaling</span> <span class="hljs-title">exponentially</span> “
        “<span class="hljs-title">thanks</span> <span class="hljs-title">to</span> <span class="hljs-title">Zero</span><span class="hljs-operator">-</span><span class="hljs-title">Knowledge</span> (<span class="hljs-title">ZK</span>) <span class="hljs-title">technology</span>. <span class="hljs-title">Think</span> <span class="hljs-title">of</span> <span class="hljs-title">it</span> <span class="hljs-title"><span class="hljs-keyword">as</span></span> <span class="hljs-title">a</span> <span class="hljs-title">total</span> “
        “<span class="hljs-title">brain</span> <span class="hljs-title">transplant</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title">the</span> <span class="hljs-title">blockchain</span>, “
        “<span class="hljs-title">similar</span> <span class="hljs-title">in</span> <span class="hljs-title">scale</span> <span class="hljs-title">to</span> ‘<span class="hljs-title">The</span> <span class="hljs-title">Merge</span>’.”
        “<span class="hljs-title">Instead</span> <span class="hljs-title">of</span> <span class="hljs-title">every</span> <span class="hljs-title">validator</span> <span class="hljs-title">re</span><span class="hljs-operator">-</span><span class="hljs-title">doing</span> <span class="hljs-title">every</span> <span class="hljs-title">single</span> <span class="hljs-title">transaction</span>, “
        “<span class="hljs-title">they</span>’<span class="hljs-title">ll</span> <span class="hljs-title">soon</span> <span class="hljs-title">just</span> <span class="hljs-title">verify</span> <span class="hljs-title">tiny</span> <span class="hljs-title">ZK</span><span class="hljs-operator">-</span><span class="hljs-title">proofs</span>. “
        “<span class="hljs-title">This</span> <span class="hljs-title">shift</span> <span class="hljs-title">could</span> <span class="hljs-title">eventually</span> <span class="hljs-title">skyrocket</span> <span class="hljs-title">Ethereum</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> 30 “
        “<span class="hljs-title">transactions</span> <span class="hljs-title">per</span> <span class="hljs-title">second</span> <span class="hljs-title">to</span> <span class="hljs-title">a</span> <span class="hljs-title">staggering</span> 10,000. “
        “<span class="hljs-title">The</span> <span class="hljs-title">best</span> <span class="hljs-title">part</span>? <span class="hljs-title">It</span>’<span class="hljs-title">s</span> <span class="hljs-title">so</span> <span class="hljs-title">efficient</span> <span class="hljs-title">you</span> <span class="hljs-title">could</span> <span class="hljs-title">theoretically</span> “
        “<span class="hljs-title">run</span> <span class="hljs-title">a</span> <span class="hljs-title">node</span> <span class="hljs-title">on</span> <span class="hljs-title">a</span> <span class="hljs-title">smartphone</span>. <span class="hljs-title">While</span> <span class="hljs-title">it</span>’<span class="hljs-title">s</span> <span class="hljs-title">a</span> <span class="hljs-title">multi</span><span class="hljs-operator">-</span><span class="hljs-title">year</span> <span class="hljs-title">journey</span>, “
        “2026 <span class="hljs-title"><span class="hljs-keyword">is</span></span> <span class="hljs-title">when</span> <span class="hljs-title">the</span> <span class="hljs-title">real</span> <span class="hljs-title">speed</span> <span class="hljs-title">revolution</span> <span class="hljs-title">begins</span>.”),
    “<span class="hljs-title">voice_id</span>”: “<span class="hljs-title">chat_0407_5</span><span class="hljs-operator">-</span>1”,
    “<span class="hljs-title">voice_language</span>”: “<span class="hljs-title">en</span>”,
    “<span class="hljs-title">voice_speed</span>”: 1.2,

}

<span class="hljs-title">response</span> <span class="hljs-operator">=</span> <span class="hljs-title">requests</span>.<span class="hljs-title">post</span>(<span class="hljs-title">AUDIO_URL</span>, <span class="hljs-title">headers</span><span class="hljs-operator">=</span><span class="hljs-title">headers</span>, <span class="hljs-title">json</span><span class="hljs-operator">=</span><span class="hljs-title">payload</span>)
<span class="hljs-title">print</span>(<span class="hljs-title">response</span>.<span class="hljs-title">json</span>())</code></pre><p>The code snippet above takes a text from a Cointelegraph article as input, along with the <code>voice_id</code>, the <code>voice_language</code> and the <code>voice_speed</code>. The output is the URL for the voice file and the audio id. The response looks like this:</p><pre data-type="codeBlock" text="{’code’: 0, ‘message’: ‘SUCCEED’, ‘request_id’: ‘f14a385d-20b8-45a8-8469-b00d2aaded65’, ‘data’: {’task_id’: ‘835047569842642979’, ‘task_status’: ‘succeed’, ‘task_result’: {’audios’: [{’id’: ‘835047569859411990’, ‘url’: ‘https://v16-kling-fdl.klingai.com/bs2/klingai-kling-input-stunt-sgp/muse/834731746867421228/AUDIO/20251231/d147f6fa9948f358602fa42cd956bb21-f9dc5b57-6d5a-4e0b-8f37-fe06572484b0?cacheKey=ChtzZWN1cml0eS5rbGluZy5tZXRhX2VuY3J5cHQSsAFGHCN_CgjsePaPU4pF4kLs3wTWpJBrE6KgbqzxUmj753zYHmfUr372mu1-CGXxj0PJ0GTW-XLYGUjUYGHx2uENIrR53Ud_K8H3JnHMj-1YFkqx8dEVNnvpTVqylkCUqCEujdgRNETYMqctNaJdWzg3ymVJGWPQ-Ur5QKyoFPpmWzP9If7YAeN3pRXlpTYjIZNM68E_kZeGIzUAMBv2Ml60ebpaIkk9yuBeMvh8DLZBbxoSOFvh80_9xnI_XufDmu_AA0PdIiA1c1FjVWNODooKSYUEUJ6KO8OkJ3eiwBnzMN53F6ne9igFMAE&amp;x-kcdn-pid=112781&amp;ksSecret=7ba1734ea6d1d4e041b846623705b975&amp;ksTime=697ba710’, ‘duration’: ‘39.384’}]}}}"><code>{’code’: 0, ‘message’: ‘SUCCEED’, ‘request_id’: ‘f14a385d-20b8-45a8-8469-b00d2aaded65’, ‘data’: {’task_id’: ‘835047569842642979’, ‘task_status’: ‘succeed’, ‘task_result’: {’audios’: [{’<span class="hljs-built_in">id</span>’: ‘835047569859411990’, ‘url’: ‘https://v16-kling-fdl.klingai.com/bs2/klingai-kling-input-stunt-sgp/muse/834731746867421228/AUDIO/20251231/d147f6fa9948f358602fa42cd956bb21-f9dc5b57-6d5a-4e0b-8f37-fe06572484b0?cacheKey=ChtzZWN1cml0eS5rbGluZy5tZXRhX2VuY3J5cHQSsAFGHCN_CgjsePaPU4pF4kLs3wTWpJBrE6KgbqzxUmj753zYHmfUr372mu1-CGXxj0PJ0GTW-XLYGUjUYGHx2uENIrR53Ud_K8H3JnHMj-1YFkqx8dEVNnvpTVqylkCUqCEujdgRNETYMqctNaJdWzg3ymVJGWPQ-Ur5QKyoFPpmWzP9If7YAeN3pRXlpTYjIZNM68E_kZeGIzUAMBv2Ml60ebpaIkk9yuBeMvh8DLZBbxoSOFvh80_9xnI_XufDmu_AA0PdIiA1c1FjVWNODooKSYUEUJ6KO8OkJ3eiwBnzMN53F6ne9igFMAE&amp;x-kcdn-pid=112781&amp;ksSecret=7ba1734ea6d1d4e041b846623705b975&amp;ksTime=697ba710’, ‘duration’: ‘39.384’}]}}}</code></pre><p>Now we’re going to use the audio <code>id</code> and an image to generate the video.</p><p>This is the avatar image I used in my video:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/4d805975c5d5e5b49b8d6e27f843432f3cd127cc598aa9a4ae4bf9ce84069e4c.jpg" alt="" blurdataurl="data:image/png;base64,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" nextheight="1024" nextwidth="1024" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Avatar image edited with Nano Banana Pro</figcaption></figure><p>Here’s the script to generate the video:</p><pre data-type="codeBlock" text="import requests
import base64

with open(”character_female.png”, “rb”) as image_file:
    image_data = image_file.read()
    img_base64 = base64.b64encode(image_data).decode(”utf-8”)

headers = {
    “Authorization”: f”Bearer {API_TOKEN}”,
    “Content-Type”: “application/json”
}

payload = {
    “image”: img_base64,
    “audio_id”: 835047569859411990,
    “mode”: “std”,
    “prompt”: (
        “Create a realistic talking avatar with a natural smile and focused”
        “, confident expression, speaking directly to the camera.”
        “\n\nCamera &amp; Background: Keep the camera fixed and do not move or “
        “alter the background in any way.\n\n”“Body Movement:\n”
        “Add subtle, natural upper-body movements (slight torso “
        “shifts, gentle head tilts, minimal shoulder motion) to avoid a “
        “static or robotic appearance.\n\n”
        “Performance style: Calm, engaging, and professional—natural speech “
        “rhythm, smooth facial animations, and realistic eye and “
        “mouth movements.\n\n”
        “Overall quality: Photorealistic lighting, stable framing, “
        “and lifelike motion without exaggeration.”)
}

response = requests.post(
    “https://api-singapore.klingai.com/v1/videos/avatar/image2video”,
    headers=headers,
    json=payload)


print(response.json())"><code><span class="hljs-keyword">import</span> <span class="hljs-title">requests</span>
<span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">base64</span>

<span class="hljs-title">with</span> <span class="hljs-title">open</span>(”<span class="hljs-title">character_female</span>.<span class="hljs-title">png</span>”, “<span class="hljs-title">rb</span>”) <span class="hljs-title"><span class="hljs-keyword">as</span></span> <span class="hljs-title">image_file</span>:
    <span class="hljs-title">image_data</span> <span class="hljs-operator">=</span> <span class="hljs-title">image_file</span>.<span class="hljs-title">read</span>()
    <span class="hljs-title">img_base64</span> <span class="hljs-operator">=</span> <span class="hljs-title">base64</span>.<span class="hljs-title">b64encode</span>(<span class="hljs-title">image_data</span>).<span class="hljs-title">decode</span>(”<span class="hljs-title">utf</span><span class="hljs-operator">-</span>8”)

<span class="hljs-title">headers</span> <span class="hljs-operator">=</span> {
    “<span class="hljs-title">Authorization</span>”: <span class="hljs-title">f</span>”<span class="hljs-title">Bearer</span> {<span class="hljs-title">API_TOKEN</span>}”,
    “<span class="hljs-title">Content</span><span class="hljs-operator">-</span><span class="hljs-title">Type</span>”: “<span class="hljs-title">application</span><span class="hljs-operator">/</span><span class="hljs-title">json</span>”
}

<span class="hljs-title">payload</span> <span class="hljs-operator">=</span> {
    “<span class="hljs-title">image</span>”: <span class="hljs-title">img_base64</span>,
    “<span class="hljs-title">audio_id</span>”: 835047569859411990,
    “<span class="hljs-title">mode</span>”: “<span class="hljs-title">std</span>”,
    “<span class="hljs-title">prompt</span>”: (
        “<span class="hljs-title">Create</span> <span class="hljs-title">a</span> <span class="hljs-title">realistic</span> <span class="hljs-title">talking</span> <span class="hljs-title">avatar</span> <span class="hljs-title">with</span> <span class="hljs-title">a</span> <span class="hljs-title">natural</span> <span class="hljs-title">smile</span> <span class="hljs-title">and</span> <span class="hljs-title">focused</span>”
        “, <span class="hljs-title">confident</span> <span class="hljs-title">expression</span>, <span class="hljs-title">speaking</span> <span class="hljs-title">directly</span> <span class="hljs-title">to</span> <span class="hljs-title">the</span> <span class="hljs-title">camera</span>.”
        “\<span class="hljs-title">n</span>\<span class="hljs-title">nCamera</span> <span class="hljs-operator">&amp;</span> <span class="hljs-title">Background</span>: <span class="hljs-title">Keep</span> <span class="hljs-title">the</span> <span class="hljs-title">camera</span> <span class="hljs-title"><span class="hljs-keyword">fixed</span></span> <span class="hljs-title">and</span> <span class="hljs-title">do</span> <span class="hljs-title">not</span> <span class="hljs-title">move</span> <span class="hljs-title">or</span> “
        “<span class="hljs-title">alter</span> <span class="hljs-title">the</span> <span class="hljs-title">background</span> <span class="hljs-title">in</span> <span class="hljs-title">any</span> <span class="hljs-title">way</span>.\<span class="hljs-title">n</span>\<span class="hljs-title">n</span>”“<span class="hljs-title">Body</span> <span class="hljs-title">Movement</span>:\<span class="hljs-title">n</span>”
        “<span class="hljs-title">Add</span> <span class="hljs-title">subtle</span>, <span class="hljs-title">natural</span> <span class="hljs-title">upper</span><span class="hljs-operator">-</span><span class="hljs-title">body</span> <span class="hljs-title">movements</span> (<span class="hljs-title">slight</span> <span class="hljs-title">torso</span> “
        “<span class="hljs-title">shifts</span>, <span class="hljs-title">gentle</span> <span class="hljs-title">head</span> <span class="hljs-title">tilts</span>, <span class="hljs-title">minimal</span> <span class="hljs-title">shoulder</span> <span class="hljs-title">motion</span>) <span class="hljs-title">to</span> <span class="hljs-title">avoid</span> <span class="hljs-title">a</span> “
        “<span class="hljs-title">static</span> <span class="hljs-title">or</span> <span class="hljs-title">robotic</span> <span class="hljs-title">appearance</span>.\<span class="hljs-title">n</span>\<span class="hljs-title">n</span>”
        “<span class="hljs-title">Performance</span> <span class="hljs-title">style</span>: <span class="hljs-title">Calm</span>, <span class="hljs-title">engaging</span>, <span class="hljs-title">and</span> <span class="hljs-title">professional</span>—<span class="hljs-title">natural</span> <span class="hljs-title">speech</span> “
        “<span class="hljs-title">rhythm</span>, <span class="hljs-title">smooth</span> <span class="hljs-title">facial</span> <span class="hljs-title">animations</span>, <span class="hljs-title">and</span> <span class="hljs-title">realistic</span> <span class="hljs-title">eye</span> <span class="hljs-title">and</span> “
        “<span class="hljs-title">mouth</span> <span class="hljs-title">movements</span>.\<span class="hljs-title">n</span>\<span class="hljs-title">n</span>”
        “<span class="hljs-title">Overall</span> <span class="hljs-title">quality</span>: <span class="hljs-title">Photorealistic</span> <span class="hljs-title">lighting</span>, <span class="hljs-title">stable</span> <span class="hljs-title">framing</span>, “
        “<span class="hljs-title">and</span> <span class="hljs-title">lifelike</span> <span class="hljs-title">motion</span> <span class="hljs-title">without</span> <span class="hljs-title">exaggeration</span>.”)
}

<span class="hljs-title">response</span> <span class="hljs-operator">=</span> <span class="hljs-title">requests</span>.<span class="hljs-title">post</span>(
    “<span class="hljs-title">https</span>:<span class="hljs-comment">//api-singapore.klingai.com/v1/videos/avatar/image2video”,</span>
    <span class="hljs-title">headers</span><span class="hljs-operator">=</span><span class="hljs-title">headers</span>,
    <span class="hljs-title">json</span><span class="hljs-operator">=</span><span class="hljs-title">payload</span>)


<span class="hljs-title">print</span>(<span class="hljs-title">response</span>.<span class="hljs-title">json</span>())</code></pre><p>After running this script, the video may take some time to become available, depending on the audio length. Be sure to add a delay before proceeding to the fetch step. This snippet produces the following output:</p><pre data-type="codeBlock" text="{’code’: 0, ‘message’: ‘SUCCEED’, ‘request_id’: ‘d6b40d68-6866-4b31-849e-a301036d0b14’, ‘data’: {’task_id’: ‘835047984131473475’, ‘task_status’: ‘submitted’, ‘created_at’: 1767119472638, ‘updated_at’: 1767119472638}}"><code>{’<span class="hljs-selector-tag">code</span>’: <span class="hljs-number">0</span>, ‘message’: ‘SUCCEED’, ‘request_id’: ‘d6b40d68-<span class="hljs-number">6866</span>-<span class="hljs-number">4</span>b31-<span class="hljs-number">849</span>e-a301036d0b14’, ‘data’: {’task_id’: ‘<span class="hljs-number">835047984131473475</span>’, ‘task_status’: ‘submitted’, ‘created_at’: <span class="hljs-number">1767119472638</span>, ‘updated_at’: <span class="hljs-number">1767119472638</span>}}</code></pre><p>In the next and final step, we’re going to use the <code>request_id</code> and <code>task_id</code> to obtain the video URL. Here’s how:</p><pre data-type="codeBlock" text="request_id = “d6b40d68-6866-4b31-849e-a301036d0b14”
task_id = ‘835047984131473475’

url = f”https://api-singapore.klingai.com/v1/videos/avatar/image2video/{request_id}”


headers = {
    “Authorization”: f”Bearer {API_TOKEN}”,
    “Content-Type”: “application/json”
}

payload = {
    “task_id”: task_id,
}

response = requests.get(
    url,
    headers=headers,
    json=payload)


print(response.json())"><code>request_id <span class="hljs-operator">=</span> “d6b40d68<span class="hljs-number">-6866</span><span class="hljs-operator">-</span>4b31<span class="hljs-operator">-</span>849e<span class="hljs-operator">-</span>a301036d0b14”
task_id <span class="hljs-operator">=</span> ‘<span class="hljs-number">835047984131473475</span>’

url <span class="hljs-operator">=</span> f”https:<span class="hljs-comment">//api-singapore.klingai.com/v1/videos/avatar/image2video/{request_id}”</span>


headers <span class="hljs-operator">=</span> {
    “Authorization”: f”Bearer {API_TOKEN}”,
    “Content<span class="hljs-operator">-</span>Type”: “application<span class="hljs-operator">/</span>json”
}

payload <span class="hljs-operator">=</span> {
    “task_id”: task_id,
}

response <span class="hljs-operator">=</span> requests.get(
    url,
    headers<span class="hljs-operator">=</span>headers,
    json<span class="hljs-operator">=</span>payload)


print(response.json())</code></pre><p>The response has the video URL from where you can download the video:</p><pre data-type="codeBlock" text="{’code’: 0, ‘message’: ‘SUCCEED’, ‘request_id’: ‘151d0403-a017-42af-89af-668d0c2ff53a’, ‘data’: {’task_id’: ‘835047984131473475’, ‘task_status’: ‘succeed’, ‘task_info’: {}, ‘task_result’: {’videos’: [{’id’: ‘835047984186015791’, ‘url’: ‘https://v16-kling-fdl.klingai.com/bs2/upload-ylab-stunt-sgp/muse/834731746867421228/VIDEO/20251231/7bc028554e69b8b6c9527496bdfc00e6-901b7d5a-40c3-4f54-b4da-d499cfe599d7.mp4?cacheKey=ChtzZWN1cml0eS5rbGluZy5tZXRhX2VuY3J5cHQSsAH1weioZR4lXm4IjZ4hSNdgLYXSg-qYje0OYPNG_RCV-L7ISZHkFYzkwOvZ-Q2YpAt514WqvbwsB7Y648-4JFYOg0pQV_9rn2AL6UgS2MPLQDcnjSwhk4URxBFL9kKceOwExCp7a2LwoJ7MSjYgJn1HOi661_f17mkhyCzCGmGQcjsrM7x8-7IUb6iLMJ95L8jrGaln6YfxLxwRLHwHOzK2MrP334DYiQaJW7p_KrmcDhoSv3Uc89R3_xETrF65D8P8-8MOIiD_d69m8PnwyzUGrpf3N1pm6gCX1XJxFgrwpIp9kHIlCigFMAE&amp;x-kcdn-pid=112781&amp;ksSecret=29b1f4a65600c88cac188b609446c9bc&amp;ksTime=697baad9’, ‘duration’: ‘39.466’}]}, ‘task_status_msg’: ‘’, ‘created_at’: 1767119472638, ‘updated_at’: 1767120346646}}"><code>{’<span class="hljs-selector-tag">code</span>’: <span class="hljs-number">0</span>, ‘message’: ‘SUCCEED’, ‘request_id’: ‘<span class="hljs-number">151</span>d0403-a017-<span class="hljs-number">42</span>af-<span class="hljs-number">89</span>af-<span class="hljs-number">668</span>d0c2ff53a’, ‘data’: {’task_id’: ‘<span class="hljs-number">835047984131473475</span>’, ‘task_status’: ‘succeed’, ‘task_info’: {}, ‘task_result’: {’videos’: [{’id’: ‘<span class="hljs-number">835047984186015791</span>’, ‘url’: ‘https://v16-kling-fdl.klingai.com/bs2/upload-ylab-stunt-sgp/muse/<span class="hljs-number">834731746867421228</span>/VIDEO/<span class="hljs-number">20251231</span>/<span class="hljs-number">7</span>bc028554e69b8b6c9527496bdfc00e6-<span class="hljs-number">901</span>b7d5a-<span class="hljs-number">40</span>c3-<span class="hljs-number">4</span>f54-b4da-d499cfe599d7.mp4?cacheKey=ChtzZWN1cml0eS5rbGluZy5tZXRhX2VuY3J5cHQSsAH1weioZR4lXm4IjZ4hSNdgLYXSg-qYje0OYPNG_RCV-L7ISZHkFYzkwOvZ-Q2YpAt514WqvbwsB7Y648-<span class="hljs-number">4</span>JFYOg0pQV_9rn2AL6UgS2MPLQDcnjSwhk4URxBFL9kKceOwExCp7a2LwoJ7MSjYgJn1HOi661_f17mkhyCzCGmGQcjsrM7x8-<span class="hljs-number">7</span>IUb6iLMJ95L8jrGaln6YfxLxwRLHwHOzK2MrP334DYiQaJW7p_KrmcDhoSv3Uc89R3_xETrF65D8P8-<span class="hljs-number">8</span>MOIiD_d69m8PnwyzUGrpf3N1pm6gCX1XJxFgrwpIp9kHIlCigFMAE&amp;x-kcdn-pid=<span class="hljs-number">112781</span>&amp;ksSecret=<span class="hljs-number">29</span>b1f4a65600c88cac188b609446c9bc&amp;ksTime=<span class="hljs-number">697</span>baad9’, ‘duration’: ‘<span class="hljs-number">39.466</span>’}]}, ‘task_status_msg’: ‘’, ‘created_at’: <span class="hljs-number">1767119472638</span>, ‘updated_at’: <span class="hljs-number">1767120346646</span>}}</code></pre><p>Here’s the final output:</p><div data-type="embedly" src="https://vimeo.com/1150452758?fl=ip&amp;fe=ec" data="{&quot;provider_url&quot;:&quot;https://vimeo.com/&quot;,&quot;description&quot;:&quot;This is \&quot;Kling AI Standard Avatar Video\&quot; by Marco Rodrigues on Vimeo, the home for high quality videos and the people who love them.&quot;,&quot;title&quot;:&quot;Kling AI Standard Avatar Video&quot;,&quot;author_name&quot;:&quot;Marco Rodrigues&quot;,&quot;height&quot;:960,&quot;thumbnail_width&quot;:960,&quot;width&quot;:960,&quot;html&quot;:&quot;&lt;iframe loading=\&quot;lazy\&quot; class=\&quot;embedly-embed\&quot; src=\&quot;//cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fplayer.vimeo.com%2Fvideo%2F1150452758%3Fapp_id%3D122963&amp;dntp=1&amp;display_name=Vimeo&amp;url=https%3A%2F%2Fvimeo.com%2F1150452758&amp;image=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F2101330979-785c6d69b98c63154a7820f951b41095d8c2c52c7bfadea04d0737c690890044-d_960%3Fregion%3Dus&amp;type=text%2Fhtml&amp;schema=vimeo\&quot; width=\&quot;960\&quot; height=\&quot;960\&quot; scrolling=\&quot;no\&quot; title=\&quot;Vimeo embed\&quot; frameborder=\&quot;0\&quot; allow=\&quot;autoplay; fullscreen; encrypted-media; picture-in-picture;\&quot; allowfullscreen=\&quot;true\&quot;&gt;&lt;/iframe&gt;&quot;,&quot;author_url&quot;:&quot;https://vimeo.com/user203866235&quot;,&quot;version&quot;:&quot;1.0&quot;,&quot;provider_name&quot;:&quot;Vimeo&quot;,&quot;thumbnail_url&quot;:&quot;https://storage.googleapis.com/papyrus_images/ce5ceb1df7894ee4bb7e63fffc11753fcf9bb99562b0133a8972d0edd678caed.jpg&quot;,&quot;type&quot;:&quot;video&quot;,&quot;thumbnail_height&quot;:960,&quot;image&quot;:{&quot;base64&quot;:&quot;data:image/png;base64,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&quot;,&quot;img&quot;:{&quot;width&quot;:960,&quot;height&quot;:960,&quot;src&quot;:&quot;https://storage.googleapis.com/papyrus_images/ce5ceb1df7894ee4bb7e63fffc11753fcf9bb99562b0133a8972d0edd678caed.jpg&quot;}}}" format="iframe"><link rel="preload" as="image" href="https://storage.googleapis.com/papyrus_images/ce5ceb1df7894ee4bb7e63fffc11753fcf9bb99562b0133a8972d0edd678caed.jpg"><div class="react-component embed my-5" data-drag-handle="true" data-node-view-wrapper="" style="white-space:normal"><a class="link-embed-link" href="https://vimeo.com/1150452758?fl=ip&amp;fe=ec" target="_blank" rel="noreferrer"><div class="link-embed"><div class="flex-1"><div><h2>Kling AI Standard Avatar Video</h2><p>This is "Kling AI Standard Avatar Video" by Marco Rodrigues on Vimeo, the home for high quality videos and the people who love them.</p></div><span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-link h-3 w-3 my-auto inline mr-1"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>https://vimeo.com/</span></div><img src="https://storage.googleapis.com/papyrus_images/ce5ceb1df7894ee4bb7e63fffc11753fcf9bb99562b0133a8972d0edd678caed.jpg"></div></a></div></div><p>This video alone consumed around 16% of the total points available (I’m using the cheapest API pricing plan). This means that with $9.79, I can generate up to six videos, if they all have the same length.</p><hr><h3 id="h-automate-posts-on-social-media" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><strong>Automate posts on social media</strong></h3><p>If you want to automate social media posts on platforms like X, Bluesky, and Instagram, you can use either cron jobs on your local machine or a remote VPS.</p><p>I prefer running automation and web scraping on a <a target="_blank" rel="" class="dont-break-out" href="https://www.anrdoezrs.net/click-101540368-17083170">Contabo VPS</a>, using my local machine only for testing. This keeps my main workstation free and avoids unnecessary RAM and resource usage.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/96f74238578bb1d0f63db837f00ced7e273a758100f824f4544c33f5c2775d0e.jpg" alt="" blurdataurl="data:image/png;base64,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" nextheight="562" nextwidth="963" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Contabo’s VPS <a target="_blank" rel="" class="dont-break-out" href="https://www.anrdoezrs.net/click-101540368-17083170"><u>main page</u></a></figcaption></figure><p>I’m currently using the <a target="_blank" rel="" class="dont-break-out" href="https://www.anrdoezrs.net/click-101540368-17083170">Cloud VPS 30</a> for only €11.2/month, which has 24 GB RAM (more than my laptop), 8 vCPU Cores, and 400 GB SSD. This plan is more than enough for most automation tasks, but feel free to have a look at the other VPS and VDS options available.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/3bc1431bdd39a82f51d4731b37415bf58e7ba4a95f6141f6d8aba61b29d04b5e.jpg" alt="" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAPCAIAAAAK4lpAAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFLElEQVR4nDWQfWwTdRjHf/xHYjDElz8USQTU+PKnCsYYE+NLYDFBkA3RLeiEySJMHVpeMkeU8DLnUpgDI2TMBMPcdOu4lRvtdqW7dWvX7srd2rt2Xds777q1vWt77fX1er2dKdX/ns/3efJ8v88DAABgVyt4+xCoawMvvlXFl3eB3e2g7hjY2VrFx58D9afBri/BB9+CdY9Ulb06UHcU1J8Cz2yv4s7DYO93oP4EeKepijveB/s7wJ7jYP/JKn52qEXTNAz3hpjIKi/AMFxR1zy+AOVfFpIpFEX9gWUmEvVSS+yqQFI+qxVd5RMY7g0zq6EwYzKZi0plfoHwUEurfMI2YxPTEuFdwnBvrqRc6x8AB5sPF/P5znbdlZ/18Tg/Bo1LGenyxZ/O6E7GojHEYsHc7pvXbnS2nxgZHCYpHwQZob9Gz3ec0Z+7iGEYBEG4C9Ofu/DjqY55uwOxWEiPp6+rp7NdZzVP9g8MgJbWoxkxuXXL5uHBP1LJBAzDUib9+o5XTuvacxkRRVGCwBs/2le3812X3eb1eIaGhhvq9wAAdO1t9xDEYrHq2r/auGH9m2+8No0gMzO2G/3Xt23ZvHHD+mnEdLn3F9Dc0sqlC9+c7bV4mPvL7J1xKJYtdfb9Pmi2kxERQaZwKnDLbL86POEKxZ0LOAzf7frt5pGOC6PofYwMTE2ab40jn+vO9v15x8cl7iHILOb5+uwlXddVVipe7u0DlwZh8PSnYGszeGwfePUYGaDB9jawqQk81Qg2fzLhINYd6QUPfwi2NYOHdrdcgc4PIuDJJvB8K3i0Aey/MEf4wAtfgG2HwKZG8FIL4QuC9zrApoPg2RbwxMff9xtBUiq09Zsa9YaGHkO3wb6mqt0GR0P3SJN+7Nh1k1QowliwoXukuW/8gN5AhKN0XGzUGw5eMjR0jwzZqLJSOT5gPtAz2tAz+sMQWlHVX2GsvuvvJv1YyxUjHUuBbDYXY0N0gIqEAhWlXCyWEqssG/RxQV8uK1XUtUQ8xgQoOkBmU4k1TUuLaS7o54L+SCggy3I+X4ixYTpAsUFfISuVlQofjSyROBf0pwS+JJeBlM1Z0FkInvwnEl3TNFkuE14Sgs3zC/dLcqWiqqEwc3fKCsFmMS1pmhbjhUnL9DhsCobpNU3L5fPo3DwEmzHcU1HXZLnsxr3Gu5NT1pmSXK4aZDI5FJ0dMUBzjnmtaiA7nZjRCEPjsCAkNE3z+ZchyGg0wl6SrBrEeaMRHrttnLU7VVXN5QuIZRqGTRMT5mw2q6oqjhOG20YYNq1GY4pSAfl8gSQpu8NZW1eS5XCYdjhdXtKnqmpFVaNR3oVhLgzL5/OapknZHObGHU5XLB7XNK1QKFBUYM4xH1heruVjOc65gOE4UVbK8oMX5e0Op9WKEoteUUwrSsVLkojlnsPpYjlO07RwmEYsVtus3e8PqKqaSqUQi9WKzuCEN5fPlxUFxwkUtdXuk+VyKBRGURvmxovFYtVATEszM3O2WTuK2ghisawoBOFFLFa73elwOEuyTDOseRKphUgmU2I6XetarWgoFC4risPhRNFZ18ICSfkURfH7A5MIgmFuYnFRFDNAEESaYVkuwnIRjltJJkWOW6FppqYIQjIW50NhmuUiNMPyQkIQkqEww3IrNMOuRmOJZIph2AfzKyy3ks7kYnG+StwKw3CCkAS8kE4kpURS4oU0L6Rj8RQvZGqYSEqxuFgr/sfU//jfTE1JiTnKH8IJyk2QboL0+GlvKEoEONzH/QuGDxad7bjeXAAAAABJRU5ErkJggg==" nextheight="533" nextwidth="1100" class="image-node embed"><figcaption htmlattributes="[object Object]" class=""><a target="_blank" rel="" class="dont-break-out" href="https://www.anrdoezrs.net/click-101540368-17083170"><u>Contabo’s VPS</u></a> pricing</figcaption></figure><p>When it comes to social media posting, I’ve previously written two articles. One for X (former Twitter) and another for BlueSky.</p><h4 id="h-create-a-bot-to-publish-on-x" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0"><strong>Create a bot to publish on X</strong></h4><div data-type="embedly" src="https://blog.dadhalfdev.com/p/x-api-v2-documentation-is-a-complete" data="{&quot;provider_url&quot;:&quot;https://blog.dadhalfdev.com&quot;,&quot;description&quot;:&quot;Instead of using the X API V2 documentation, make a bot on steroids with these steps.&quot;,&quot;title&quot;:&quot;Learn How to Build a Bot on X Step-by-Step With This Tutorial&quot;,&quot;author_name&quot;:&quot;Marco Rodrigues&quot;,&quot;url&quot;:&quot;https://blog.dadhalfdev.com/p/x-api-v2-documentation-is-a-complete&quot;,&quot;thumbnail_url&quot;:&quot;https://storage.googleapis.com/papyrus_images/eeb9270d947bbc7c7e5f242b18614e4bb3ecee4e6a1aaff58874a6b69568fe17.jpg&quot;,&quot;thumbnail_width&quot;:1200,&quot;version&quot;:&quot;1.0&quot;,&quot;provider_name&quot;:&quot;Dadhalfdev&quot;,&quot;type&quot;:&quot;link&quot;,&quot;thumbnail_height&quot;:600,&quot;image&quot;:{&quot;base64&quot;:&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAQCAIAAAD4YuoOAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEOElEQVR4nL2UbUxbZRTH70Ri3Idp4nRlJCYzMrPEZY5khkQ0k0Ri4ie3zLnE+TZf4nQugMmSqUCV8iIwhF5LRwstre0d17ZAW2opdDYV2uW2F6EtpfbdthTXl1va3pZCoY+5okLFbxqTf05Ong/P75zz/J8DgYzgnzSMJRPyVaD614L+RwA5vEs8Y4IYTwDln/ovAHkR2BCB9W+pJC80ZzMqEmhIoCaBJgPU6R3MdjJBFLF38uJqIEAKQFYIMoK4m7nqg3Phm1FnT9RxY9xuG7SEUW8c9SUFtuXRcE5DUleoU2AqRyXaDUqaDFClqMPtUtRpKu7pIM2fUX1qm21RoQ19HW+48Y4FfVOLUMyzrTSw+Fe62fCPFoZsSuSITGcB6ku2SCfVafClRPO5QNokGhc744pYgWt2i10x1Jsc8RDFgALim+v4xdaVjXE+uFT78ktV9OuvAJIjMlu6p+cqq5+rffVii1SjJEDrmFa3BcTO6HXed+oU+Kir/9pNYTOi4FuC0lAG1s2zDfZhe4iLe5REMcCBMWLevlz45hLW9jPeDne/uRbsHTbijcgEHVHwLEEO5pRHC12Ts9NZoIyD0ZV1xBNH/SntGhiLrCtiQBbOihx3JQFSEiCloaw6VQxw4u0RVx/YQnD9F3E3Mx3jkFGW0GSSxzcRZwTWz6OB1OjKetekUbsBZOFc720zbyHQq8UmCNBvXJQE0iMeok2uhWesbMMi22BH/cm/Hh8C4JbVwHCZWsG6iMd612lqm5R8IuNfbhMIrvTy+NZgHZPDs/jHIvnO7w1TaxQAcRGycE4Wyk4QQBbMiF2xEc+qNJSVR/J/2Cm+uwNi0HGnlfDA589WQ9C95888Q6M9fOCBB2m0R0pLSiqrTx8qO0wrL+dgTli3oMsDSYDkml1swyLzB1yZAKg3MTjnGzDaeQt+nsWvJoFylTLVDqAQ44yK65btPcz215uunT35VAUE3bN//4F9EPTQwYP3lZQcKis78vjRzwRS1qxNHt2UhrJc3IN6E1T0JRFPfBD3ot4kB3MOzfu2rfx3F1kNjFHhVVzXbLrd3EG/cPrZ46+dq75w+f2yR4/sg6Cna144dvLU0SdPPFbxRM2Zc6g/WdfLqWcO1n/Db2ANf/gVTEdV9TDv4x7219OYJrMXsIUEl3qkwqsOjLG2zI66mNh0k8fSKrHib9E7q2pfPFZ56v7S0qqaWgiC3mPcoJz6u9+p6TvjkgApC2YQF4F44vJdoy/+aEm+caqRC79z6eLzAz1vWw0Mu4HeODAE6y0NrGHa4XJaOaWK4yckgbQyAQaMS1yzG56xDc37mDocnrF2TxoHTA75r/nd09+1KtYEgBQELZ0L+uY5XfOSkeH7qX0Eu9Ont7FmbRzMxTG5+41LYmdUTVIraOxuXkkAeXRTEQPyaEEe2RqL5BWxgiJW2NvBb8fqiAH8iKSPAAAAAElFTkSuQmCC&quot;,&quot;img&quot;:{&quot;width&quot;:1200,&quot;height&quot;:600,&quot;src&quot;:&quot;https://storage.googleapis.com/papyrus_images/eeb9270d947bbc7c7e5f242b18614e4bb3ecee4e6a1aaff58874a6b69568fe17.jpg&quot;}}}" format="small"><link rel="preload" as="image" href="https://storage.googleapis.com/papyrus_images/eeb9270d947bbc7c7e5f242b18614e4bb3ecee4e6a1aaff58874a6b69568fe17.jpg"><div class="react-component embed my-5" data-drag-handle="true" data-node-view-wrapper="" style="white-space:normal"><a class="link-embed-link" href="https://blog.dadhalfdev.com/p/x-api-v2-documentation-is-a-complete" target="_blank" rel="noreferrer"><div class="link-embed"><div class="flex-1"><div><h2>Learn How to Build a Bot on X Step-by-Step With This Tutorial</h2><p>Instead of using the X API V2 documentation, make a bot on steroids with these steps.</p></div><span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-link h-3 w-3 my-auto inline mr-1"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>https://blog.dadhalfdev.com</span></div><img src="https://storage.googleapis.com/papyrus_images/eeb9270d947bbc7c7e5f242b18614e4bb3ecee4e6a1aaff58874a6b69568fe17.jpg"></div></a></div></div><h4 id="h-create-a-bot-to-publish-on-bluesky" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0"><strong>Create a bot to publish on BlueSky</strong></h4><div data-type="embedly" src="https://blog.dadhalfdev.com/p/easy-steps-to-automate-your-posts?r=1t52ml&amp;utm_campaign=post&amp;utm_medium=web" data="{&quot;provider_url&quot;:&quot;https://blog.dadhalfdev.com&quot;,&quot;description&quot;:&quot;Use the BlueSky Python SDK and some creativity to automate posts on BlueSky for free.&quot;,&quot;title&quot;:&quot;Easy Steps to Automate Your Posts on BlueSky with Python&quot;,&quot;author_name&quot;:&quot;Marco Rodrigues&quot;,&quot;url&quot;:&quot;https://blog.dadhalfdev.com/p/easy-steps-to-automate-your-posts&quot;,&quot;thumbnail_url&quot;:&quot;https://storage.googleapis.com/papyrus_images/f5eaf7da64f2c7eea2f3c4cb35008ae229b0ce935a6113d7d53ed52c0a7447ba.jpg&quot;,&quot;thumbnail_width&quot;:1200,&quot;version&quot;:&quot;1.0&quot;,&quot;provider_name&quot;:&quot;Dadhalfdev&quot;,&quot;type&quot;:&quot;link&quot;,&quot;thumbnail_height&quot;:600,&quot;image&quot;:{&quot;base64&quot;:&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAQCAIAAAD4YuoOAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEMklEQVR4nL2UfUxbVRjGr1FU/jGLMwO6aZapiW5LdCpmxrm4zS3xDxOXuE2nJMQFxGQqbuJ0AjVrKWMDBuO2dLTjtr39wOugDEvXMmAV6Eda2Nrb0t6U0jYUCvSTtrcUV8oxLbAQhMTExOTJSe45Oef3nuc+54VAXLCR+PpIuGsOyP+zoP8RQAoAyV8Vog2HboeBbFWPNqz7XJ75F4B5AXgoAn8J00qKQBI1xGMyEvSQQLE8xoAsc5YyDnri6Z2KaHpSPreyKt8EA6ULn0dBHJ1zMsmJ5uRsS8hxPeRolNsJxOJrd83dmiCFNn/nbFKRgaGED7VOpwsPAhHhk4eB0DqNuaPLsE1uQPKHFL/gQzRlexmrvtA+XPOgv4LGE3JNk2U3+KWNLbDKWNVxV0T4VClQq1QXXKAWUhlUcRdVfPubuuYSRj1bY+2dB92hDQFLEteDK25TbSLAKT5z7KMP8+mVnwKSIxzGG/qN+w4cPHziM3pHjywIqjv7VItAbA+2GMYwV4Rn9rA1Vh7uaXOGMXdkM5fSAEJfFXDCC162TccgDIyG6oIFTyNfN1Iu6q5EpQg+wdYRXf6lK92DagAuItjxr86eb+aXMOrLbqAXkd9Z6tH+xY3LXwHYDdW+sesgKRn581JwHI75uaSfheoN0sCieMzXpDJirjnpdLJWqe1LALHdDw/gV+9o4EGcpbZc7lIJLFMKctMsQQC0mbVVdgMDpCSilq8dIzW9nRe6RN/WSETfs1DUOnmOyRNYJjt9yat3NH0PAeYMIya30DYttvv51imhbVo6m5RHVwH/CDEEQjftBkZwHP7i1EEIevL0J+9RKNu2bHmWQsnJznoi/9DR3O07KC/s5BgcTSqjKgV4Zg9LbUFwN4JPiMcCN42udu/C3UQmtdHVTEfXAFJ+jlRcOmNrqKWdLv/h432vvwxB0NPZz0AQtPW5rU89Dm3Lzd2xa1cFKmVrRmVBgLkikvEg5o6iVi/miiD4BA/38MyTQtuMiAj8Nh5CTO4O78IjRvof4Bq6VFh6/94lfd+v9IpTB97de/L4OyeLivKe3/kYBOUfOro3f/8rr73x0u49R058LrLNwAM4d9ghsExx9HbmIF6nHOLoCcwZ5pk9HJ2NOYivPIuMVxBISTy2+nb0O0JfnfCy/WNNGmWFw8i4ZR4pKL/81vsf7Hnz7eysrP2Hj0EQVMJoxNwReuZNtBrdihho1o5e69GhVi9iSpuWtigO5GstSjeJcKtWWYmwiosLj3CbzhD6aruORuW2wkOjP7L4OXl5OXl5uZTtL766Wzqb4A47fua2FdFqzzF5ihho6NP/xJWch5EvK+ln65hsHSELrgOQApAQgCjivF+j763U91ItappjuEqkGbp2zwQPmFjq0WatDR40o1avgsx0oRj4I7C0th2tnBgFnb7UuhT9DWbugSR/WC4tAAAAAElFTkSuQmCC&quot;,&quot;img&quot;:{&quot;width&quot;:1200,&quot;height&quot;:600,&quot;src&quot;:&quot;https://storage.googleapis.com/papyrus_images/f5eaf7da64f2c7eea2f3c4cb35008ae229b0ce935a6113d7d53ed52c0a7447ba.jpg&quot;}}}" format="small"><link rel="preload" as="image" href="https://storage.googleapis.com/papyrus_images/f5eaf7da64f2c7eea2f3c4cb35008ae229b0ce935a6113d7d53ed52c0a7447ba.jpg"><div class="react-component embed my-5" data-drag-handle="true" data-node-view-wrapper="" style="white-space:normal"><a class="link-embed-link" href="https://blog.dadhalfdev.com/p/easy-steps-to-automate-your-posts?r=1t52ml&amp;utm_campaign=post&amp;utm_medium=web" target="_blank" rel="noreferrer"><div class="link-embed"><div class="flex-1"><div><h2>Easy Steps to Automate Your Posts on BlueSky with Python</h2><p>Use the BlueSky Python SDK and some creativity to automate posts on BlueSky for free.</p></div><span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-link h-3 w-3 my-auto inline mr-1"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>https://blog.dadhalfdev.com</span></div><img src="https://storage.googleapis.com/papyrus_images/f5eaf7da64f2c7eea2f3c4cb35008ae229b0ce935a6113d7d53ed52c0a7447ba.jpg"></div></a></div></div><p>If you want to build an avatar like mine that talks about crypto, tech, and world news, you’ll need a web scraper to extract fresh daily content. This content can then be summarized and used as the audio script for your avatar.</p><p>If you’re not familiar with summarizing content using LLMs and Python, take a look at the <a target="_blank" rel="" class="dont-break-out" href="https://blog.dadhalfdev.com/p/x-api-v2-documentation-is-a-complete?r=1t52ml&amp;utm_campaign=post&amp;utm_medium=web">article above</a> on building bots for X.</p><p>As for the web scraper, if you’re short on ideas, you can use one of mine:</p><ul><li><p><a target="_blank" rel="" class="dont-break-out" href="https://apify.com/dadhalfdev/aljazeera-scraper-per-event?fpr=ulosg"><strong>Aljazeera Scraper</strong></a>: Extract articles from Aljazeera, providing essential insights into current events and regional tensions.</p></li><li><p><a target="_blank" rel="" class="dont-break-out" href="https://apify.com/dadhalfdev/techcrunch-scraper-per-event?fpr=ulosg"><strong>TechCrunch Scraper</strong></a><strong>: </strong>Get the latest tech and AI news from TechCrunch.</p></li><li><p><a target="_blank" rel="" class="dont-break-out" href="https://apify.com/dadhalfdev/cointelegraph-scraper-per-event?fpr=ulosg"><strong>Cointelegraph Scraper</strong></a><strong>: </strong>Extract data from Cointelegraph, a leading platform for cryptocurrency and blockchain-related news.</p></li></ul><p>You can find many other scrapers available on <a target="_blank" rel="" class="dont-break-out" href="https://apify.com/store?fpr=ulosg">Apify</a>.</p><h4 id="h-do-you-need-help-with-automation-web-scraping-ai-data-or-anything-that-my-laptop-can-deliver-feel-free-to-reach-me-on-upwork" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0"><strong><em>Do you need help with automation, web scraping, AI, data, or anything that my laptop can deliver? Feel free to reach me on Upwork! </em></strong><span data-name="man_technologist" class="emoji" data-type="emoji">👨‍💻</span></h4><div data-type="customButton" href="https://www.upwork.com/freelancers/~01185447baa36a1b77" class="center-contents"><a class="email-subscribe-button" href="https://www.upwork.com/freelancers/~01185447baa36a1b77">Let's build together!</a></div><hr><h3 id="h-conclusion" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><strong>Conclusion</strong></h3><p>The costs associated with creating a single avatar video can quickly add up. For example, with less than $10, I would only be able to publish six videos in total.</p><p>That said, this expense is relatively small when compared to the time and effort required to produce a traditional social media video. Recording myself talking about the latest crypto news would involve multiple takes, video editing, and careful audio adjustments.</p><p>All of these manual steps are far more costly than a couple of dollars per video.</p><p>An avatar that consistently generates content can instead be used to drive traffic to your website, support affiliate marketing, or power other growth strategies.</p><p>As we’ve seen at the beginning of this article, users are consuming more AI-generated videos than ever. The real challenge is creating an engaging, value-driven avatar. One that can generate passive income while you sleep.</p><p>Curious about what I’m building? <span data-name="eyes" class="emoji" data-type="emoji">👀</span></p><div data-type="subscribeButton" class="center-contents"><a class="email-subscribe-button" href="https://paragraph.com/@dadhalfdev/subscribe">Subscribe</a></div><br>]]></content:encoded>
            <author>dadhalfdev@newsletter.paragraph.com (Dad Half Dev)</author>
        </item>
        <item>
            <title><![CDATA[5 Tips to Turn You Into a Pro Web Scraper With Playwright]]></title>
            <link>https://paragraph.com/@dadhalfdev/5-tips-to-turn-you-into-a-pro-web-scraper-with-playwright</link>
            <guid>J1FAziyuoLC6iLWwabBu</guid>
            <pubDate>Sun, 28 Dec 2025 22:38:02 GMT</pubDate>
            <description><![CDATA[Web scraping seems to have taken the lead in internet traffic. Following the 2025 Imperva Bad Bot Report, 51% of global web traffic is now automated, surpassing humans. A key element in this is Artificial Intelligence (AI), which requires vast amounts of data for model training and therefore relies on massive crawlers running nonstop. At the same time, AI has also made web scraping more accessible, allowing non-developers to collect data through vibe coding and seamless APIs. According to a r...]]></description>
            <content:encoded><![CDATA[<p>Web scraping seems to have taken the lead in internet traffic. Following the <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://www.imperva.com/blog/2025-imperva-bad-bot-report-how-ai-is-supercharging-the-bot-threat/">2025 Imperva Bad Bot Report</a>, 51% of global web traffic is now automated, surpassing humans.</p><p>A key element in this is Artificial Intelligence (AI), which requires vast amounts of data for model training and therefore relies on massive crawlers running nonstop. At the same time, AI has also made web scraping more accessible, allowing non-developers to collect data through <em>vibe coding</em> and seamless APIs.</p><p>According to a <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://www.marketresearchfuture.com/reports/web-scraper-software-market-10347">report</a> by Market Research Future, the web scraper software market was valued <strong>$1.01 billion in 2024</strong>. In 2025, the <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://www.mordorintelligence.com/industry-reports/web-scraping-market#:~:text=The%20Web%20Scraping%20Market%20size,2030">Mordor Intelligence report</a> shows that the same market is now valued at <strong>$1.03 billion</strong>, a steady <strong>1.98%</strong> increase in just one year. The same report projects that the web scraping market will reach <strong>$2 billion by 2030</strong>, nearly <strong>98%</strong> growth in just six years.</p><p>While web scraping is more accessible with the integration of AI, many websites have also shielded themselves against massive bot requests. Making the job difficult for many APIs and web scrapers powered by <em>vibe coding</em> scripts.</p><p>In this piece, I’m sharing with you 5 tips that Large Language Models (LLMs) don’t tell you to build a robust web scraper that can outperform 90% of the websites with only one tool: <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://playwright.dev/python/">Playwright</a>.</p><hr><h1 id="h-first-steps-with-playwright" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">First steps with Playwright</h1><p>At the time I’m writing, I have <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://apify.com/dadhalfdev">over 20 Apify actors</a> running, all built using Playwright.</p><p>Before, I used to web scrape with <a target="_blank" rel="noopener ugc nofollow noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://www.selenium.dev/documentation/">Selenium</a>, <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/">Beautiful Soup</a>, and <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://www.scrapy.org/">Scrapy,</a> but I’ve realized that I can have successful bots only using Playwright, so why complicate things?</p><p><a target="_blank" rel="noopener ugc nofollow noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://playwright.dev/python/">Playwright</a> is a headless browser considered to be faster than its competitors and with better support for modern websites. Documentation is easy to follow and supports multiple languages.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/690a89b4a616c790ba161e0b081da0742b1840c12b73bce291dc0d87d700ec0a.jpg" alt="" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAQCAIAAAD4YuoOAAAACXBIWXMAAAsTAAALEwEAmpwYAAAD4ElEQVR4nJ2S3U8iVxjGZ9lu6hfOgBtbrSDKwJxhPMPAyIADrAK68rW42EWRlfpVkQ1CSmGX1UgQqxJddJddramusYnJJm2zafqR9K7/Qdtkb7xpetG7pr1umjQpDagNtq5pe/LLyfueM+d5Ms85COyi+O4ei8VqNHUbTd0qSq1mWKDq0Gh1LMsRKmg0mjVaXYukVSKVXUCLpJU3mm94vD0Wa6sMv/wKdrURf60ZRwDsBPRZNLrKlmINJMMdQzGnNa0/mWm96ni9VJcOEpAlIAtgp5Iq1QjJdJGsgaS7SGgAKj1Q6ZVKjiA5UEZB6SQ41SKnpDiUKmgp3tEOGAlOyQEjVUCpAsoItVQBJTjVDhgZoZYR6rIgfzKzPEIyBhLqabPRkh7gp+xcwMbP2PmpfuOdfj5mt4/6Uvez2eW1rZ39lbWHd+cywcnwRmEnu7yeWVrb3j2Yjadiibn04upCdnUhmwtF3lXrTIDmSrJlyga0QaXvInv1zMg104yj8y1Lh8fYk3JTQ7zJbY8l5pPzi+lsLhxNhKKJwNh0OJqYjadm46l789mJUDQwFroTu+sPTo1PRyZCsUr1EwMC6vSm3vyD9wubT5ff28zntvf2nh18+PHjR0+zy+u59UIqvRSOJnL5x2sbW0+295Zy+alwbCGbe7S1u7iynpzL7O4fbhR2gpNhqYKiSvmcNQA0x3Bmrz84GAhanR6P/7ZvdMJsczgGfLcC49ddb3qHg32uQd/opH/sbd/I+OBw0Oa4OTgU9AenB26N+gKTybnMRCjq8g7TZ/M5jYgxEBpOb7FanZ4bvhGux+YeCjz//MuPPvlsd/8Q0JwcMAqqs41QtxHqdsAct3LAtBGMHGhLF453yBQ0Tmorpc8YkKzBYOkzX3daHR69pa/XNRCN35+Np0KRdyBrpFhDGb6Cv7UnnGPw1x7QlLIiYOkHCagrvUsctirguUL/HqRdQZ0CK2pKTkAc0Dig5ccrBCxxstVx/IEc0HJAV576J4hQiL4MFMUEdQ1IPYZh4ipBVQ2C1AvRBpH4igBDUdGlS1eQ8rhAQShEERQVvYyqGpEGq9ahtQhS3aQkm6/Z6mpQBBESJCasr9VptEPjMy6PVywSXyByvgFWVpdJRUfxleJhIeCU2j/48V7x9/6Hvi13269fP/tiu3v1+Xf5P4pf/VJk1FqB4FUR1vAfDFBMXHsZa2av+l98+3Pxm40Mw0d+UC4kO8PW37wjxfzRT5vO9KcvEkfFB98Xddr/YVCmrkbU5MLDM2+8XlclYNwCzW0EEZqr8YMmI1Hd4PTcjCwfRpLZpsbG8oWdH9GfyE9VzdHa9l4AAAAASUVORK5CYII=" nextheight="566" nextwidth="1100" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Playwright for Python <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--figure-anchor" href="https://playwright.dev/python/">website</a></figcaption></figure><p>To install <a target="_blank" rel="noopener ugc nofollow noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://playwright.dev/python/">Playwright</a>, you need the following <code>pip</code> command:</p><pre data-type="codeBlock" text="pip install playwright"><code></code></pre><p>To install the supported browsers, use this command in your terminal:</p><pre data-type="codeBlock" text="playwright install"><code></code></pre><p>Now, the basic component of Playwright is often called <code>page</code> and it is instantiated this way:</p><pre data-type="codeBlock" text="from playwright.async_api import async_playwright


async with async_playwright() as pw:

    # creates an instance of the Chromium browser and launches it
    browser = await pw.chromium.launch(headless=False)

    # creates a new browser page (tab) within the browser instance
    page = await browser.new_page()"><code><span class="hljs-keyword">from</span> playwright.async_api <span class="hljs-keyword">import</span> async_playwright


<span class="hljs-keyword">async</span> <span class="hljs-keyword">with</span> async_playwright() <span class="hljs-keyword">as</span> pw:

    <span class="hljs-comment"># creates an instance of the Chromium browser and launches it</span>
    browser = <span class="hljs-keyword">await</span> pw.chromium.launch(headless=<span class="hljs-literal">False</span>)

    <span class="hljs-comment"># creates a new browser page (tab) within the browser instance</span>
    page = <span class="hljs-keyword">await</span> browser.new_page()</code></pre><p>I will not cover all of Playwright’s functions in this piece, but I will highlight the ones I use in most of my crawlers and have proven to be indispensable:</p><pre data-type="codeBlock" text="# Go to page and wait to render full content: images, APIs and more
await page.goto(”some_url”, wait_until=”networkidle”)

# Go to page and wait only for DOM structure (initial HTML). Much faster.
await page.goto(”some_url”, wait_until=”domcontentloaded”)

# Create some timing between actions
await page.wait_for_timeout(3000)

# Get text content only
await page.locator(”a”).text_content()

# Get an attribute
await page.locator(”a”).get_attribute(”href”)

# Get all elements with the same class
elements = await page.locator(”a.font-big”).all()

# Click the first element
await page.locator(”a.font-big”).first.click()

# Click the last element
await page.locator(”a.font-big”).last.click()

# Click element by index
await page.locator(”a.font-big”).nth(3).click()"><code># Go to page and wait to render full content: images, APIs and more
await page.goto(”some_url”, wait_until<span class="hljs-operator">=</span>”networkidle”)

# Go to page and wait only <span class="hljs-keyword">for</span> DOM structure (initial HTML). Much faster.
await page.goto(”some_url”, wait_until<span class="hljs-operator">=</span>”domcontentloaded”)

# Create some timing between actions
await page.wait_for_timeout(<span class="hljs-number">3000</span>)

# Get text content only
await page.locator(”a”).text_content()

# Get an attribute
await page.locator(”a”).get_attribute(”href”)

# Get all elements with the same class
elements <span class="hljs-operator">=</span> await page.locator(”a.font-big”).all()

# Click the first element
await page.locator(”a.font-big”).first.click()

# Click the last element
await page.locator(”a.font-big”).last.click()

# Click element by index
await page.locator(”a.font-big”).nth(<span class="hljs-number">3</span>).click()</code></pre><p>In addition to these examples, it is also useful to use <code>page.get_by_role()</code>, <code>page.get_by_title()</code>, <code>page.get_by_label()</code>, and so on, whenever you can. This is usually more straightforward than using the <code>page.locator()</code>.</p><p>For more about Playwright’s functions, visit the well-structured <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://playwright.dev/python/docs/intro">official documentation</a>.</p><p>Now we will have a look at the 5 tips to improve your web scraping skills while integrating Playwright. They aim at answering the following questions:</p><ol><li><p>How to increase the stealth performance?</p></li><li><p>How to intercept the website’s HTTP response?</p></li><li><p>How to handle infinite scroll websites?</p></li><li><p>How to target HTML elements accurately?</p></li><li><p>How to make proper proxy rotation?</p></li></ol><p>Let’s get started!</p><hr><h3 id="h-1-how-to-increase-the-stealth-performance" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">1 - How to increase the stealth performance?</h3><p>If you’re familiar with Playwright, you’ve probably heard of <code>playwright_stealth</code>.</p><p>While it can work for some websites, it is definitely an outdated solution to improve your stealth performance.</p><p>The alternative: <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://camoufox.com/python/"><strong>Camoufox</strong></a><strong>.</strong></p><p>This open-source anti-detect browser can be integrated with the Playwright API. It works by providing Camoufox with detailed device characteristics, including the operating system, device information, navigator properties, headers, screen size, and more.</p><p>To install Camoufox, use this <code>pip</code> command:</p><pre data-type="codeBlock" text="pip install -U camoufox"><code>pip install <span class="hljs-operator">-</span>U camoufox</code></pre><p>Your playwright’s <code>page</code> object can be instantiated in the following way:</p><pre data-type="codeBlock" text="from camoufox import AsyncCamoufox

async with AsyncCamoufox(
    os=”macos”,
    humanize=True,  # Enable humanized cursor movement
    headless=False,  # Keep visible for debugging
    window=(1280, 720),  # Set window size
) as browser:

  page = await browser.new_page()"><code>from camoufox import AsyncCamoufox

async with AsyncCamoufox(
    <span class="hljs-attr">os</span>=”macos”,
    <span class="hljs-attr">humanize</span>=<span class="hljs-literal">True</span>,  <span class="hljs-comment"># Enable humanized cursor movement</span>
    <span class="hljs-attr">headless</span>=<span class="hljs-literal">False</span>,  <span class="hljs-comment"># Keep visible for debugging</span>
    <span class="hljs-attr">window</span>=(<span class="hljs-number">1280</span>, <span class="hljs-number">720</span>),  <span class="hljs-comment"># Set window size</span>
) as browser:

  <span class="hljs-attr">page</span> = await browser.new_page()</code></pre><p>Using this browser won’t solve all your issues. You may still get blocked by websites protected by Datadome, but it is significantly better than using Playwright only.</p><p>You can also add proxies, tweak the parameters, and add <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://camoufox.com/python/browserforge/">BrowserForge</a> to see if the stealth is improved.</p><hr><h3 id="h-2-how-to-intercept-the-websites-http-response" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">2 - How to intercept the website’s HTTP response?</h3><p>Many developers who engage in web scraping tend to strictly extract and parse the HTML content. While this solution works, it may not be the fastest way to crawl data, and you may miss important metadata and features.</p><p>Many modern websites don’t load all their data in the initial HTML. Instead, they fetch data dynamically from APIs (such as JSON and GraphQL) after the page loads.</p><p>Therefore, before tackling the HTML content, check if the website has an API response. This can be triggered by simply loading the page, clicking on buttons, or scrolling the page.</p><p>Let’s take the <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://hackernoon.com/">Hackernoon</a> website as an example.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b560d0e402a58cc1e868fa8ad91e83065ef0a2c09d51fd8a6546490d0fe7555f.jpg" alt="" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAQCAIAAAD4YuoOAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEn0lEQVR4nGWTW2zbZBTHv8hYztX+nMTxJa6TLJdmYxeJCcG0Dk2baIO6aRtiIE1iD+yVCSZNQiAx9rA9jDdAYnuDwQhbpV4ULhNMDFiZKtgLSKgdNMuadmqWtnHseLbjerZRYlqy8ZP96ZMln/85/3MOWFiYl2W51WqpirywpNy6Ld6bn1tYuFetVue7LC4uqmtIkrTSaLzy4ktxLpXPb82k87nspky6vz+3Zdu2ndnMpnz/FkFIb9yQy6dzqWQum9kIFEV5oKq6rhtGW2ppK03DNA1zDcPo3J01LMtyHOfwgcM0zXNskmMTgpBmGUEQ0qlklo+nBCHNMQJN98WoOB6I0jQPbNtZNVZN09T1VcdxTNNQVU1V1VZLkeWWqqqaprdaiqKostyyLEtR1OF9R8Ikl0nnYxTnRo9RXJxLbkjlaJrv4zcIQjoaYagoGyEZMDtT2XXk1UsTY2+fGL4984fcUqZnpiuVSrlcvnPnTrVaNU1T7Zaoqg9s2xLF5u7dBQAAhhIoAgEIIEgIAC8AXg/wA4ACgHUvXsTjR5EQaCw1P58o/T49/cN3Rbkp/j1fHr9eMvS2LMvOo9hdHMcZfuEAAE9AGGPZTvpuynw8lUpmn9y4PZXK8/EUH0+534H7T+ftYqyuapo2OTlZLBbHxsZGRkZKpZKiKOsNcBynMDhMUXGajgcCYRIyJKRJSBNELMmw29OZrJAiYQwPRCERgwTlCti2Yzu2tS6k63qra7wkSYqi/JvEWgWFvc9HIixFcYjHiyIhDCU8wO9DCcqPB1CfD/EiXbvcB1z/a+Xib7VPpubOffvn6Su/1JZEXdfqSx0ajYamac1mU5IkURQ1TXO19wzsYhghSrEo4sdQwodBFAmFMIIlwrgPdqzvuO/HkCCGBsGH18tPvXuZ2Hlo26krO975dGTim9LE+NLycq1Wq9frmqa12+3eeVUUZeCZZzk22amgR8CHwZAP5wiSJ2CCJBPhcMSLh70hUPrxVuHocTqz9fjp9y+MX7v4xZcnTrwpimKtVnNXzOlpsuM47XZ778AulklEo+xjAognxBMwy1BCOMxBSPnxEBYEclOsL95bEZvuyLv7dePGjWKxODo6KknSemj3dBxn/1Chs0oxrteiztSiRMRP8ATkCRgniEQ4zBIEsGz7oW0bbV3X25bdidK7uuvYtm11cRxn3+BQjOYp6nEBHxrM0NE0TSUiYQYnOZxkcAh+rsofXf312MDTp0+e/HpOrS83Wi357t0516JarXb//v1KpVKv15vNptvn/UMFhhZoOv6oAPRheB8ZEahwNEqHSBoAP/AEwcXJmedeP5dihOyOA29d+umrq99fOH9eFEWpiyiKiqLIsmwYxno1Lx88lMlsSiTSCOL9TwCDAQxG/DiDQzqIx/w45cdJHw7OfvDZ5t1H3zj18eY9xw6+9t7oeOnsmTOLtVq5XJ6dnV1eXu51yb3sHxyKRFiG6fNh8DGL+pkoH6NjQcgEQ3GCZHEITNO0Or4/NM2HlmW5UW7evHm5y9TU1P+bvG+wACHT3785GmEQj793imJBmGOoPjKSjIR5EhIY/g/cfQvL2+qC8AAAAABJRU5ErkJggg==" nextheight="551" nextwidth="1100" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Network response on the Hackernoon <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--figure-anchor" href="https://hackernoon.com/">website</a></figcaption></figure><p>In this case, there’s a JSON API response for each article that contains a lot of useful information about it, including the title, the slug, the ID, the author’s name, the image, and even the article’s body.</p><p>To extract the information from the JSON, you need to place this code before the event is triggered:</p><pre data-type="codeBlock" text="# Create set to track processed article IDs
processed_ids = set()

# Get response and set up response listener
response_received = asyncio.Event()
page.on(
    “response”,
    lambda response: check_json(
        response, response_received, processed_ids))"><code><span class="hljs-comment"># Create set to track processed article IDs</span>
<span class="hljs-attr">processed_ids</span> = set()

<span class="hljs-comment"># Get response and set up response listener</span>
<span class="hljs-attr">response_received</span> = asyncio.Event()
page.on(
    “response”,
    lambda response: check_json(
        response, response_received, processed_ids))</code></pre><p>Now you can create a function to save the content in JSON format or CSV:</p><pre data-type="codeBlock" text="async def check_json(response, response_received, processed_ids):
    “”“ Get data from HackerNoon JSON response “”“

    url_response = (”https://hackernoon.com/_next/data/”)

    if url_response in response.url:
        try:
            items = await response.json()
            article_data = items[’pageProps’][’data’]
        except Exception as e:
            return

        if article_data:
            response_received.set()

            # Extract article features based on example.json structure
            try:
                article_id = article_data.get(’id’)
                
                # Check for duplicates using article ID
                if article_id in processed_ids:
                    return
                
                # Add to processed IDs set
                processed_ids.add(article_id)
                
                profile = article_data.get(’profile’, {})
                
                # Extract stats data
                stats = article_data.get(’stats’, {})
                
                post_data = {
                    ‘id’: article_id,
                    ‘title’: article_data.get(’title’),
                    ‘slug’: article_data.get(’slug’),
                    ‘link’: “https://hackernoon.com/” + \
                        article_data.get(’slug’),
                    ‘excerpt’: article_data.get(’excerpt’),
                    ‘tldr’: article_data.get(’tldr’),
                    ‘articleBody’: article_data.get(’articleBody’),
                    ‘createdAt’: article_data.get(’createdAt’),
                    ‘mainImage’: article_data.get(’mainImage’),
                    ‘mainImageHeight’: article_data.get(’mainImageHeight’),
                    ‘mainImageWidth’: article_data.get(’mainImageWidth’),
                    ‘socialPreviewImage’: article_data.get(
                        ‘socialPreviewImage’),
                    ‘parentCategory’: article_data.get(’parentCategory’),
                    ‘tags’: article_data.get(’tags’, []),
                    ‘commentsCount’: article_data.get(’commentsCount’),
                    ‘pageViews’: stats.get(’pageviews’),
                    ‘arweave’: article_data.get(’arweave’),
                    ‘author_name’: profile.get(’displayName’),
                    ‘author_handle’: profile.get(’handle’),
                    ‘author_avatar’: profile.get(’avatar’),
                    ‘author_bio’: profile.get(’bio’),
                    ‘author_isBrand’: profile.get(’isBrand’),
                    ‘author_isTrusted’: profile.get(’isTrusted’)
                }

                # Save “post_data “data to JSON or CSV
                    
            except Exception as e:
                print(”Error extracting article data: %s”, str(e))   "><code>async def check_json(response, response_received, processed_ids):
    “”“ Get data from HackerNoon JSON response “”“

    url_response = (”https://hackernoon.com/_next/data/”)

    if url_response in response.url:
        try:
            items = await response.<span class="hljs-built_in">json</span>()
            article_data = items[’pageProps’][’data’]
        except Exception as e:
            return

        if article_data:
            response_received.<span class="hljs-built_in">set</span>()

            # Extract article features based on example.json structure
            try:
                article_id = article_data.<span class="hljs-built_in">get</span>(’id’)
                
                # Check for duplicates using article ID
                if article_id in processed_ids:
                    return
                
                # Add to processed IDs set
                processed_ids.<span class="hljs-built_in">add</span>(article_id)
                
                profile = article_data.<span class="hljs-built_in">get</span>(’profile’, {})
                
                # Extract stats data
                stats = article_data<span class="hljs-selector-class">.get</span>(’stats’, {})
                
                post_data = {
                    ‘id’: article_id,
                    ‘title’: article_data.<span class="hljs-built_in">get</span>(’title’),
                    ‘slug’: article_data.<span class="hljs-built_in">get</span>(’slug’),
                    ‘link’: “https://hackernoon.com/” + \
                        article_data.<span class="hljs-built_in">get</span>(’slug’),
                    ‘excerpt’: article_data.<span class="hljs-built_in">get</span>(’excerpt’),
                    ‘tldr’: article_data.<span class="hljs-built_in">get</span>(’tldr’),
                    ‘articleBody’: article_data.<span class="hljs-built_in">get</span>(’articleBody’),
                    ‘createdAt’: article_data.<span class="hljs-built_in">get</span>(’createdAt’),
                    ‘mainImage’: article_data.<span class="hljs-built_in">get</span>(’mainImage’),
                    ‘mainImageHeight’: article_data.<span class="hljs-built_in">get</span>(’mainImageHeight’),
                    ‘mainImageWidth’: article_data.<span class="hljs-built_in">get</span>(’mainImageWidth’),
                    ‘socialPreviewImage’: article_data.<span class="hljs-built_in">get</span>(
                        ‘socialPreviewImage’),
                    ‘parentCategory’: article_data.<span class="hljs-built_in">get</span>(’parentCategory’),
                    ‘tags’: article_data.<span class="hljs-built_in">get</span>(’tags’, []),
                    ‘commentsCount’: article_data.<span class="hljs-built_in">get</span>(’commentsCount’),
                    ‘pageViews’: stats.<span class="hljs-built_in">get</span>(’pageviews’),
                    ‘arweave’: article_data.<span class="hljs-built_in">get</span>(’arweave’),
                    ‘author_name’: profile.<span class="hljs-built_in">get</span>(’displayName’),
                    ‘author_handle’: profile.<span class="hljs-built_in">get</span>(’handle’),
                    ‘author_avatar’: profile.<span class="hljs-built_in">get</span>(’avatar’),
                    ‘author_bio’: profile.<span class="hljs-built_in">get</span>(’bio’),
                    ‘author_isBrand’: profile.<span class="hljs-built_in">get</span>(’isBrand’),
                    ‘author_isTrusted’: profile.<span class="hljs-built_in">get</span>(’isTrusted’)
                }

                # Save “post_data “data <span class="hljs-selector-tag">to</span> JSON or CSV
                    
            except Exception as e:
                <span class="hljs-built_in">print</span>(”Error extracting article data: %s”, <span class="hljs-built_in">str</span>(e))   </code></pre><p>Where do you see the URL response? You can find it in <em>Headers</em> under <em>Network</em> by inspecting the website’s page.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/0d2faefb1bd4ae546b18433d452757eb1e14eadffcb2dde976e13926586c6708.jpg" alt="" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAQCAIAAAD4YuoOAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFbUlEQVR4nE1Ua0xTZxj+mqarbaGlN07PrefantOWgheWXdQoKrcYlzmBzQGbGs1uWaZuxj/LljnxgoCVlouayTYTiUYjc8owCGhdwczggMhlZIkmFaoFSuvAegpylrYb25MnX97v+/N87/s+7wsCgUA0AeH5bCD0vPfPyOMx/9jYuN/vf5RAIBB4lsDs7KwgCD6fz27lOS7DxmdaLXaec1otNrtt2bKlqzguw2HPIkmLnbXbuKUMzXFWBxgbHw8GgxOTE6HQ1GQo/HA8FAw+jkQi4XB4cnJyamoqGAyGw+Hp6emnkYgoigMD/VbKyjI2DKUwhKQJFkMpkmBZhicJloxfSQQmoHRUp4EQmAAzkb/CE6HpiVBsRpgX5sUEFhYW5ubmBEGIRp8vLCTfxBcvXoiiODo6StGZsImiSBbDGBPKYBhNmhkIwjCUoikrbDKbIJwkLfo0k0qhATcGvG0DN9v7vO193s6R7q6hnuu9Nzt7b4+MDHZ23mxpaem8/su9u73ero7uW12/9XT//NMVvR4GQCmTqpfIdS+pIalULZMoJZIUCVDKZYkYpCyR65QKvVSSAsBGAL7RgmIAnABkAaAAIAOAFWBr6ZsAABMA72xcv2nNmkwC5hENAMBJkRznSE1NT0tNRxHCaslkaBtFWUmCxXGGJC0kwZrNDI5RBMEQBAtArhR8pAavA7ABABrEsRKAzZriokJGCupqKvruj3q9vo6OG61Xr+zf/Vlp8dssRWEYbTDAFGWx25cbjbheD8MwgWE0ilIIQqIYhaIUjjMoSiZ+7QTxDDYAYEkIaABYKfv40/KtmzedaTzY3t7u9Xb/6vN1dXXdvtXhrj2BwRhJWiAIVSg0cplamiiOGWNsfCbL8JzVwVkdFtbGWR0EwQD5rixlkRUcXm0sc6Zmo/zqrILCwrd2luz78vP3S7ed8lR3dl4fuD/ce+9eQ32Dy+VqbKhHcIxheaMR0etNJgjXpBqkkhTMTOMYDUFYsskmCDcaEIU8DfjHHw2PDI/+MTo8PDweCIQj4SfBJ6FwaGJysr+vb3Bw8MGDh2Njj/x+fzAYjEaj/f19iAlhWJteD+E4zXNOrQaSACVKkgzN6bUmmVS9SLlMDWLPYsKMMB+dF2Oi+K8jRVEUBCE+WjMzSXcu2nRwcBCBYIbhDQYTihAMwyMIqVToDHoYgnClQqdU6FJUepVCp0rEoLbb7fLFWdvjPn7bVe07XuWtbrhzsuf+3UtXW5uam39oPnf14sULFy41nT/fdLa5vvG0nbVkZb1MM1ajEVEpdAp5mlymNhoRgx7WaiBNqkEm0yyRpyUJVleuzz1SmFOZt/Zo7ppDuesr81dVrCtylxw5696+54u84uJdO3aeqzxauuXd7Xv2vLGlpLz8PQtB4jir1UIIYiYJNk1jlAAlSbBWi50kWBQhTRCuUujkUo1CrgZrG/JyPYXr6vPX1efnePJzGgte8+SUNJfuP/ZVSfmOst2fNJ30fF9x8MDeva7G2rKy0m3l5WxcgCFJ1ozHB1irgaSSFAQmUIQ0GuJ5JKsfp1wN1G4bUuM01PCIy2Go4pFqG/21M6cx/4N9H66wZe+vPORxV5fk5G8pKCgqKXplRXbe2lwLwxIEa7NnUSQLm8xaDSSTqiEIM0F4Wmp6svr/CbiunXC3ejxtdbWttZ62uqrLNYdPHz7Vcqr58vkz3/14Z+D3a23XPMeOVxyoqKyqrvXUVXxbkck7MhzZy5e9arXYUlX6+HqQqjGU4jmnhbVBEJb00j8CszOzT8NPhaiwkNhqi+fc3JwoijEhFhNi/3fR0NAQGl9sNMvyDMMZ9LBKoZNJ1UYDYjTEe75o0KTA3xVxQ1eUf0q2AAAAAElFTkSuQmCC" nextheight="551" nextwidth="1100" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Find the URL response on the Hackernoon <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--figure-anchor" href="https://hackernoon.com/">website</a></figcaption></figure><p>The <em>Response</em> tab under <em>Network</em> displays the JSON structure with all the fields you can scrape.</p><p>Now you know, next time, check this before engaging in intense HTML parsing, and note that the APIs can be triggered in different ways. Make sure to try buttons, filters, pagination, and scrolling.</p><p>This is how I built my Hackernoon Apify actor. You can try it yourself <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://apify.com/dadhalfdev/hackernoon-scraper?fpr=ulosg">here</a>.</p><hr><h3 id="h-3-how-to-handle-infinite-scroll-websites" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">3 - How to handle infinite scroll websites?</h3><p>Many modern websites use infinite scroll to improve loading speed and improve the user experience. But they are definitely not loved by web scrapers.</p><p>Dealing with infinite scrolling can be challenging because websites tend to use different strategies to load their content. Scrolls can be located on different sides of the page. Some pages might not load content if you don’t move to the exact place on the page, others might require clicking to load more content, and so on.</p><p>The simplest way to scroll a page with Playwright is by using the wheel function:</p><pre data-type="codeBlock" text="n_scrolls = 10
for i in range(n_scrolls):
      await page.mouse.wheel(0, 15000)
      print(’scrolling’)
      await page.wait_for_timeout(3000)
      await page.mouse.wheel(0, -1500)
      print(’move up’)
      await page.wait_for_timeout(3000)"><code>n_scrolls <span class="hljs-operator">=</span> <span class="hljs-number">10</span>
<span class="hljs-keyword">for</span> i in range(n_scrolls):
      await page.mouse.wheel(<span class="hljs-number">0</span>, <span class="hljs-number">15000</span>)
      print(’scrolling’)
      await page.wait_for_timeout(<span class="hljs-number">3000</span>)
      await page.mouse.wheel(<span class="hljs-number">0</span>, <span class="hljs-number">-1500</span>)
      print(’move up’)
      await page.wait_for_timeout(<span class="hljs-number">3000</span>)</code></pre><p>The reason why I’m using a loop in the example above is that most pages with infinite scroll take some time to load the hidden content. Therefore, it may not work if you just scroll to the bottom of the page. With the loop, you can ensure the new data is loaded in each iteration.</p><p>While this strategy works, sometimes you can’t trigger the loading this way. The best approach is to move the cursor to the nearest element that triggers it. In the case of a news website, most likely the last visible element is an article/card, so that’s a good reference to scroll down to.</p><p>Let’s see how to implement it.</p><pre data-type="codeBlock" text="# scroll to the item
location = page.locator(”article”).last
await location.scroll_into_view_if_needed()"><code># scroll to the item
location <span class="hljs-operator">=</span> page.locator(”article”).last
await location.scroll_into_view_if_needed()</code></pre><p>With the two code snippets above, you should be able to handle most of the infinite scroll websites. Note that the more you scroll, the harder it gets to load, and your scraper can get very slow.</p><hr><h3 id="h-4-how-to-target-html-elements-accurately" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">4 - How to target HTML elements accurately?</h3><p>Sometimes using the <code>page.locator()</code> can be a real frustration. You try several classes, attributes, and text, and still the script prompts an error.</p><p>For those cases, my first approach is to target the main classes. Meaning that if you have an element with a lot of classes, start by tackling it with only one or two classes. This will make Playwright prompt an error similar to this:</p><pre data-type="codeBlock" text="      playwright._impl._errors.Error: Locator.text_content: Error: strict mode violation: locator(”div.container-Qnseki”).first.locator(”a.pencraft.pc-reset”) resolved to 2 elements:
          1) &lt;a data-testid=”post-preview-title” href=”https://newsletter.theaiedge.io/p/adalflow-a-pytorch-like-framework” class=”pencraft pc-reset color-pub-primary-text-NyXPlw font-pub-headings-FE5byy clamp-y7pNm8 clamp-3-lxFDfR reset-IxiVJZ”&gt;AdalFlow: A PyTorch-Like Framework to Auto-Optimi…&lt;/a&gt; aka get_by_role(”link”, name=”AdalFlow: A PyTorch-Like”)
          2) &lt;a href=”https://newsletter.theaiedge.io/p/adalflow-a-pytorch-like-framework” class=”pencraft pc-reset color-primary-zABazT line-height-20-t4M0El font-text-qe4AeH size-15-Psle70 clamp-y7pNm8 clamp-2-kM02pu reset-IxiVJZ”&gt;AI Agent frameworks are becoming just as importan…&lt;/a&gt; aka get_by_role(”link”, name=”AI Agent frameworks are”)"><code>      playwright._impl._errors.Error: Locator.text_content: <span class="hljs-built_in">Error</span>: strict mode violation: locator(”div.container-Qnseki”).first.locator(”a.pencraft.pc-reset”) resolved to <span class="hljs-number">2</span> elements:
          <span class="hljs-number">1</span>) <span class="hljs-operator">&lt;</span>a data<span class="hljs-operator">-</span>testid<span class="hljs-operator">=</span>”post<span class="hljs-operator">-</span>preview<span class="hljs-operator">-</span>title” href<span class="hljs-operator">=</span>”https:<span class="hljs-comment">//newsletter.theaiedge.io/p/adalflow-a-pytorch-like-framework” class=”pencraft pc-reset color-pub-primary-text-NyXPlw font-pub-headings-FE5byy clamp-y7pNm8 clamp-3-lxFDfR reset-IxiVJZ”&gt;AdalFlow: A PyTorch-Like Framework to Auto-Optimi…&lt;/a&gt; aka get_by_role(”link”, name=”AdalFlow: A PyTorch-Like”)</span>
          <span class="hljs-number">2</span>) <span class="hljs-operator">&lt;</span>a href<span class="hljs-operator">=</span>”https:<span class="hljs-comment">//newsletter.theaiedge.io/p/adalflow-a-pytorch-like-framework” class=”pencraft pc-reset color-primary-zABazT line-height-20-t4M0El font-text-qe4AeH size-15-Psle70 clamp-y7pNm8 clamp-2-kM02pu reset-IxiVJZ”&gt;AI Agent frameworks are becoming just as importan…&lt;/a&gt; aka get_by_role(”link”, name=”AI Agent frameworks are”)</span></code></pre><p>Since it doesn’t know which element you are referring to, it will kindly present you with multiple options.</p><p>From those options, you can use the recommended Playwright function to grab it, or use <code>nth()</code> with the right index.</p><p>If your selector still doesn’t work, switching to XPath inside the <code>page.locator()</code> function can often deliver more accurate results.</p><p>This is because XPath allows you to navigate the structure of the DOM directly.</p><p>Let’s take a look at this example.</p><p>Suppose you’re trying to target a button with a dynamic class name that changes on every page load. A CSS selector like this might fail:</p><pre data-type="codeBlock" text="button = page.locator(”.dynamic-button-class”)"><code>button <span class="hljs-operator">=</span> page.locator(”.dynamic-button<span class="hljs-operator">-</span>class”)</code></pre><p>Instead, you can use an XPath expression that targets the element by its text content or position:</p><pre data-type="codeBlock" text="button = page.locator(”//button[contains(text(), ‘Submit’)]”)"><code>button <span class="hljs-operator">=</span> page.locator(”<span class="hljs-comment">//button[contains(text(), ‘Submit’)]”)</span></code></pre><p>There are also Playwright built-in functions that mimic XPath:</p><pre data-type="codeBlock" text="button = page.locator(”button”).filter(has_text=”Submit”)"><code>button <span class="hljs-operator">=</span> page.locator(”button”).filter(has_text<span class="hljs-operator">=</span>”Submit”)</code></pre><p>You can either decide to learn the XPath expression language or explore more Playwright’s documentation. But avoid very long XPath expressions to optimize code readability.</p><hr><h3 id="h-5-how-to-make-proper-proxy-rotation" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">5 - How to make proper proxy rotation?</h3><p>Some of you are familiar with proxies and proxy rotation, but the real challenge arises when choosing the right proxy for your needs.</p><p>If anonymity and avoiding raising flags are your top priorities, residential proxies are the best option. However, if you are web scraping a website that doesn’t have strong blocking measures, you may want to prioritize speed, and datacenter proxies are a better solution.</p><p>I rely on proxy rotation when scraping more challenging websites, and IPRoyal’s trustworthy <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://iproyal.com/v1/?r=526327">residential proxies</a> have consistently met my needs.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7c5df368a0f895598d7e56f98b2cd8bdd711617fc3b26d913f14a34a8de7ba16.jpg" alt="" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAOCAIAAADBvonlAAAACXBIWXMAAAsTAAALEwEAmpwYAAADDUlEQVR4nIWTW28SYRCGX71UY2JCKlqoZpFDF1ZoF7oCy8KCLWU5tEpXWqAi1dpKMSlFbau0atODrbGampgYE2Oi8cIbE+Mf8E5/gjcm3vsfMLNQUyzG5MmbyeSbd+eb+RZH5h503F0LbOzo7txHfhreKNIFJEchJ6EWERlC/BLUCcgpxFTK9F9oBjEVwXiTsUkUZ5At31gM1j8N/Pog/XznQzqJZB4olJCbQm4SN24jlYE3AkVFOAkphoRKGk5SXoohkqIgpFCQyEBOQIw2SWQwlEM8a88FluZds3PO8lwvYgp1gx6xidMHPgghTNoIPCGCl+AUCc5Pygcp2RMgFSJ07E+JJwT3APhB8FHCoznAE4BH0ggQvEgqyBCChHge4QSUYWQzyIwirEAapLzUT7h96JOaJwV510TcRTOkxgnvLj5w52BywNoDs5NqFBUjI7pa+fCtGQymaCDd7oOiDG8IjAVWF8wuOszYYe/bdWsYagE4oQXWA0FWX77B5E0UpnAxh9Erpsq9M+VFWnVxprOyiHQehWmMXcXULIozwsrW0elKfOclhrL0JWerIWy9LVhd4P3mas27ssXXVj3L64cmSvzyKlNZULZfBNae9C2v87VVW/Werbp0fmPbVl1iq0vhjafjr98jdQlmDqy7xRAmrg36U7SMwhTCcRRL6E8hMUKN9/gRHabXpRYOTJQpH1LQn0R6HJ0mMGwbK8r+hcmOLgt4MbK5g8Lk8VLFVXvoX92KPn6O3FVnbU189MxYWTDOzl949VZc35Y2n7GLD8HYqHC/G7qsbeAEatbSB5sfFi/MgqbnYPPRSlk3zZoTaNysm9bGeujGTHcbK7rafhgWZk5WucvXzg7nHbGMYzjPjV9zKRkHWCdZN55g44k7vTRrhoXB3MYKJ063Qd8FQ1f940D9R6n+LVv/rNS/jtW/X69/ScNugYlFaJD+A68MaYAuYTgDvbG9FToM/0FvxFkejBWmbg0HwXQT+lPQGUg7jP8sx7ETe9Br7M006NT0JKHrhK6hWtBSu79Q/xs4JO0YdrGqwgAAAABJRU5ErkJggg==" nextheight="469" nextwidth="1100" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">IPRoyal main <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--figure-anchor" href="https://iproyal.com/v1/?r=526327">page</a></figcaption></figure><p><a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://iproyal.com/v1/?r=526327">IPRoyal</a> proxies are also one of the cheapest in the market, with an excellent score on review platforms such as <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://www.g2.com/products/iproyal/reviews">G2</a> and <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://www.trustpilot.com/review/iproyal.com">Trustpilot</a>. You can create an account in a few seconds, without requiring too much personal information, and you can even pay with cryptocurrencies, if you don’t want to have your credit card attached to it.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a47d2e5c2a24d349328a99545f7a520128fa056f6eea71c9bf2cdcfe41387263.jpg" alt="" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAPCAIAAAAK4lpAAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEyElEQVR4nE1S7W8URRzeHtAUClxv725mdmZndm93dmd37/au7bXXUovliqUv4aVC+dCIob6kJsT3BAvxA2gFQU0oBC2xIRhJkZSXE1qxQCANb1bRWhEIpoTyhRDUxD/ADzXXFvDJk/ky8/s98zy/nwQyNcBPYdMiXBAukKJ4tp0pK1MikQJJKnrMBQXSwgJpcUAqCQRKAoHQ3ILw3IJI4RwdAcGooKoOIrZKPEpjStT2VIdSWyUYAEmLJ+yEbwpBGKOaDgDIrlmz4b2u1k2vt3S+1vhKZ/blztqOV6s2bEy/sDHR/qJY3262tbPW9XDV2nDz6uKmlXMaWqRso7RsxVPWN0p1z0n1zQstRzINQ1iWrusEY8aYHAzuH7l8bWrqm0d/f/XnP/vuP+i+fbfrtztvjt3quDq2/tqvKy6OVp48ax0fjg0M2Weu8NxI7OhZdvi0evCE2pcjfbknp95/RlrZJlmW5fu+aZqEEF3X5VDos6Hvcg//2vvTz7suj+6+cXv35IOtN+++9ftEx+j42ku/5AWGLvKT542B4djAGa3/tHrwGO497uzYfGGLkdtekdtWlttW1r/FA3t7pKZ1EmPM8zzbtgkhdNpBz9nzF/6dOnTvfu/E5J6JyY/u3Nt6c+KN6zc7Rsfbrow1jvyYGb7Ev71gDAxr/afy3Q8cUfty8qc7u7c1bulu7fpwdVd369vbW1Fvn9TcJmmaZtu2pmlPBD45PTQyNXXk4aODDx7tmZj84MYfXWO3Nv0wvjEf0XjDyPXMuat88KJx/Jx+ZJAeOkH6jqL9h2HP16jnGOoZQHvzhHsGlN6jUuNKiVLq+74QIi9AKYQwnq6saWzONDSk65en65eX1y/3s/VeXVYsreNLao3qGr26Rq2sUioysCID0hm5vLIkVRFMpuVkSk6mQslUiZ8K+ckFZRUy1fICruvOOqAUIQSiUWaYCccpjcfNWCwcDAJZRrIMZDlmci+Rcl0vLIccBLOuYxkGjoQoBBRCCiGBoDKmtyT95mRyKTdBFORnEI/HZ0yYpgkhxAS7rlPqJ5K+53tuwhOO49hCmJZFGaO6TnUdYswoLfWE5wkhuGEwSlWVUpVSnTFT00xNMzQNQjw7A0VRCCGMMUVBMoCKkxbppYZfZZU+E/OrTVsYhpFf5cdQFCWsMD21xK2otVLVIBYvBpQQdeYWT5MQAiGSOOeO4wghMMacGwBiRwPdDYHdzYU7WxbvaJr3cYOUNiIAzRZPJ6nKkGTMaFet9M6z8zcvW7S5bk5npsDUsDLT+DFmBYQQrutyzg1dCwNcakRPrps32F44+FLwVHvh922FdS6IKvkMZsoYVUNQzTqhL1cUfLEqcOD54OdNgV3LJBFTFEyo+hR5AcuyPM9LJpOe5xFCEEKRKCwO46ISWBSMzpdRcRhHIEbTgADmOY0wUBaFcbGMFsooCGgQqBBhhBSEFAjygBBGIMw7sKfBOadURRCplLhpkUr66fJy13EIxvm/Y0J1JirdeFXCLnMggsxw/NKadHmKc44VpOLZdCjVvNLaVGVWxKtgKCRhjJVpYIxn1hQpiunweDzuuM7/B6syyriuc51xHSGkMt12fT8eF8Li3DAMY/YZpTp3TEOwRLro3ff/AzVDUNKa+3qrAAAAAElFTkSuQmCC" nextheight="532" nextwidth="1100" class="image-node embed"><figcaption htmlattributes="[object Object]" class=""><a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--figure-anchor" href="https://iproyal.com/v1/?r=526327">IPRoyal</a> dashboard</figcaption></figure><p>Once logged in, you have access to a user-friendly dashboard where you can select the best proxy option for your needs. If you don’t know what works best, you can answer a short survey to help you out.</p><p>If you decide to use residential proxies like me, you’ll see a page with your username, password, hostname, port, and several filters that allow you to customize your proxy’s location.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/01b4e66493b048782b258d9ef13d24d079240b866c2e6fc46c39dd293f0dde6b.jpg" alt="" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAQCAIAAAD4YuoOAAAACXBIWXMAAAsTAAALEwEAmpwYAAADc0lEQVR4nJWU72vkRBjH07yYK2FvdqdMJpPp7M4m2WSazW426V7ctJdur62s7wQPqtxBxRd66KEv5ND648Uhhy/0RDnwxYHI0Tf6yr9ABKnoXQsq3Mv7I0T6TrQom9ldyvUs+iEE8mXyfJ955plHS7aff257++qVK0IIhBDGuO17xWA59IRFTHwKhFDQbm9sbvbWLzUvruGluCiyP3774fjo4K/fHxwfHRwfHfx59ODv44evXXvh3LmKFrTbYRgyxgghGGMIq5+8uPLTh8/+fPvy9nowB86TUzYIIQhhDcJapSLq9X4/63S6juN0Ot047rVaraDlB0Hg+369UddazWYcd1X6hBDDMAghS2E7TpJ2FDHGVFBlP4OUmOUzxaTUopQyzhtRtxFFzHUBAJqQUkZRo16vQUgIAQBAWHU8r95o+FJyzlVECKEq4AwI4cIpBUJoc87DiIcRazq6rmvu6tpiN6GOSxc5azoAAMuyunIpiSLbxNV5gDFmjKVp6vv+LJZFadLr1ZvNCoQzMSxR1VtANYzx2IA1XT9fqfcSW7is6c4bhknI8OrOM69eL3Ze8oebNrWFEMPhMM9zQgillHMuhCiKYnNrq5em47IwxjnPsmw0GmVZ5jgOpVQIURowtiQDZtsLCJkYAwAwNuXFor2x4RfDxU7PptRmYzjntIRNP52Sk6IQwnGc2cqxASHkqcFASllFyCzPwKY0v3ChWMkD161VDHgmhvHkBQihiQGldHV11fM8IQRjDABgGIZKxHEcWKvpug6m6FNmykx8TDEMg3M+MZAlnucpiXNeFEUQhrN2/O/QExBCxgac806no66P2kEVoX6/X9bRYsxmzP4fDoSgEozxZAe+76dpKqXEGHueBwCglHpeIIRbQ6amzc3p84+ldgae53VKVFtPDKSUcRxLKdUOMMa7b137/NP3bt18/f3dl998Y8cipjobwzDAmWCMhRCqwaSUE4Msy/I8j+OYlIEQQu/uvnL3zjuffXTjzu0bt25eRwhpU5TNv6HyUF1kUzr+QRmqNy7vAWPs0vraaLSVpt1GY9HzmoOslw+SfJBk/ZhS6/SIPTkHGWP9MctRsoxagaZUxXQWnb9394Nf7n91//t7h/t7h/t7P3735f63Xxzu733z9ccWMTVNm/XrE9F0fV7T5NOjt3999A/kBse+zog6sQAAAABJRU5ErkJggg==" nextheight="554" nextwidth="1100" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Residential proxy parameters on <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--figure-anchor" href="https://iproyal.com/v1/?r=526327">IPRoyal</a> dashboard</figcaption></figure><p>To implement proxy rotation, I select up to 7 different countries and cities, and I add them to a Python list in my script. It looks like this with Camoufox:</p><pre data-type="codeBlock" text="proxy_list = [
    None,  # No proxy first
    “&lt;key&gt;_country-fr_city-toulouse”,
    “&lt;key&gt;_country-es_city-valencia”,
    “&lt;key&gt;_country-pt_city-lisbon”,
    “&lt;key&gt;_country-es_city-madrid”,
    “&lt;key&gt;_country-es_city-huelva”,
    “&lt;key&gt;_country-es_city-sevilla”,
]

for proxy_element in proxy_list:
    # Configure browser settings based on whether using proxy or not
    browser_config = {
        “os”: “windows”,
        “humanize”: False,  # Enable humanized cursor movement
        “headless”: False,  # Keep visible for debugging
        “window”: (1280, 720),  # Set window size
    }
    
    # Add proxy configuration if proxy_element is not None
    if proxy_element is not None:
        browser_config.update({
            “geoip”: True,
            “proxy”: {
                “server”: “geo.iproyal.com:11201”,
                “username”: “&lt;my_username&gt;”,
                “password”: proxy_element
            },
        })
    
    async with AsyncCamoufox(**browser_config) as browser:
      # If page is accessed continue the script, if not try another proxy 

      "><code>proxy_list <span class="hljs-operator">=</span> [
    None,  # No proxy first
    “<span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>_country<span class="hljs-operator">-</span>fr_city<span class="hljs-operator">-</span>toulouse”,
    “<span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>_country<span class="hljs-operator">-</span>es_city<span class="hljs-operator">-</span>valencia”,
    “<span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>_country<span class="hljs-operator">-</span>pt_city<span class="hljs-operator">-</span>lisbon”,
    “<span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>_country<span class="hljs-operator">-</span>es_city<span class="hljs-operator">-</span>madrid”,
    “<span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>_country<span class="hljs-operator">-</span>es_city<span class="hljs-operator">-</span>huelva”,
    “<span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>_country<span class="hljs-operator">-</span>es_city<span class="hljs-operator">-</span>sevilla”,
]

<span class="hljs-keyword">for</span> proxy_element in proxy_list:
    # Configure browser settings based on whether <span class="hljs-keyword">using</span> <span class="hljs-title">proxy</span> <span class="hljs-title">or</span> <span class="hljs-title">not</span>
    <span class="hljs-title">browser_config</span> <span class="hljs-operator">=</span> {
        “<span class="hljs-title">os</span>”: “<span class="hljs-title">windows</span>”,
        “<span class="hljs-title">humanize</span>”: <span class="hljs-title">False</span>,  # <span class="hljs-title">Enable</span> <span class="hljs-title">humanized</span> <span class="hljs-title">cursor</span> <span class="hljs-title">movement</span>
        “<span class="hljs-title">headless</span>”: <span class="hljs-title">False</span>,  # <span class="hljs-title">Keep</span> <span class="hljs-title">visible</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title">debugging</span>
        “<span class="hljs-title">window</span>”: (1280, 720),  # <span class="hljs-title">Set</span> <span class="hljs-title">window</span> <span class="hljs-title">size</span>
    }
    
    # <span class="hljs-title">Add</span> <span class="hljs-title">proxy</span> <span class="hljs-title">configuration</span> <span class="hljs-title"><span class="hljs-keyword">if</span></span> <span class="hljs-title">proxy_element</span> <span class="hljs-title"><span class="hljs-keyword">is</span></span> <span class="hljs-title">not</span> <span class="hljs-title">None</span>
    <span class="hljs-title"><span class="hljs-keyword">if</span></span> <span class="hljs-title">proxy_element</span> <span class="hljs-title"><span class="hljs-keyword">is</span></span> <span class="hljs-title">not</span> <span class="hljs-title">None</span>:
        <span class="hljs-title">browser_config</span>.<span class="hljs-title">update</span>({
            “<span class="hljs-title">geoip</span>”: <span class="hljs-title">True</span>,
            “<span class="hljs-title">proxy</span>”: {
                “<span class="hljs-title">server</span>”: “<span class="hljs-title">geo</span>.<span class="hljs-title">iproyal</span>.<span class="hljs-title">com</span>:11201”,
                “<span class="hljs-title">username</span>”: “<span class="hljs-operator">&lt;</span><span class="hljs-title">my_username</span><span class="hljs-operator">&gt;</span>”,
                “<span class="hljs-title">password</span>”: <span class="hljs-title">proxy_element</span>
            },
        })
    
    <span class="hljs-title">async</span> <span class="hljs-title">with</span> <span class="hljs-title">AsyncCamoufox</span>(<span class="hljs-operator">*</span><span class="hljs-operator">*</span><span class="hljs-title">browser_config</span>) <span class="hljs-title"><span class="hljs-keyword">as</span></span> <span class="hljs-title">browser</span>:
      # <span class="hljs-title">If</span> <span class="hljs-title">page</span> <span class="hljs-title"><span class="hljs-keyword">is</span></span> <span class="hljs-title">accessed</span> <span class="hljs-title"><span class="hljs-keyword">continue</span></span> <span class="hljs-title">the</span> <span class="hljs-title">script</span>, <span class="hljs-title"><span class="hljs-keyword">if</span></span> <span class="hljs-title">not</span> <span class="hljs-title"><span class="hljs-keyword">try</span></span> <span class="hljs-title">another</span> <span class="hljs-title">proxy</span> 

      </code></pre><p>While proxy rotation is beneficial to bypass anti-bot measures, it slows down your web scraper’s speed. Therefore, if speed is a top requirement, you can rent a Virtual Private Server (VPS), so you can run your script with multiple instances and at the same time, one for each proxy.</p><p>I use Contabo’s <a target="_blank" rel="noopener ugc nofollow noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://www.anrdoezrs.net/click-101540368-17083170">Cloud VPS 30</a> for only €12.5/month, which has 24 GB RAM (more than my laptop), 8 vCPU Cores, and 400 GB SSD. This plan is more than enough for most automation tasks, but feel free to have a look at the other VPS options available.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/e0e459e36172d56bb061761fe3490aa552ccc02ac1ad84e9e13e2e5282fcf50a.jpg" alt="" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAPCAIAAAAK4lpAAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE+UlEQVR4nHWQW2wUZRTHv1a5JPigPmgUik2sMSrGRC2gBH0AQUy0hEiNiBZMeDRKmuhbExNNjAFDLG1SGlwCvUChIJBQsGxp9zaX3W3TvU5nZq+zu7Nzn9ntzuzszM5ntuVRv5yXX07O9zvnD8DGrqc6dm544e3NW98Fz7wB2l8+9ebW0zue++n1Z9/reAm0vbKlc9fGrd0btu9q69wN2rqe2LZzc8eu9q59ba8eAht2tD//1qZt3e0vvrOpcw8AXeDp17Z07n6yo3vL9p0tBAC45xDLqrMl1tBrhSKLhSKmwAhURGdIlSt60eVGXed5XhRFvVZb8OK6rgs8x3Ncw6zP+3BZViRJFAS+bugBbInjBEkUymwZOtY/bqwleDiPphLJG66JZCQhSCoeipJE6prraji0VDVMDxJeiSf+Hp+6cXlSkmRvYIkiqVtXJm+PXxd43odGaCr1YPru9OWJ5HIUD0cZpuSdcd9wjTPp1OzCmgDBowHv/MGP9seWF1lWiMRpj2d+7573A555TdPQcPT2rVtf9fb+8vNAiqbwcHJ87MoXR4/82H86TdNYKDp982bf8S9PfHN8zj0bDMfu3bv/+ZHD357om3t4/+7M3FpEC1i2zI1OTHOakc0Xg6FoSVLOuybznFoWFF8gzMuVM8MX59Clql73+MOLy7Ffzw1dvTNr2s68B40nqWHX2KWp24pu+P1BgkxdnLg+dGlSXjXu3HO3BAMTHnBoBJyaAh/+0f3bjDtEgkND4OQk2P8n+H4qTmXB4QugbxL0jIK+yxSdBycnwLEx0OsCPReiKxnQPw2OuMDXY+DAeXeQ3HNmFnz2V2v8wNDAhPe7HwZAvKAcHHx0bNS/99zcJJpW9UbPiLd3xLd/cO73mRiE8OQl9PDw/CeD8/1TYQhh/1T448FHPcMLfS7EceDZB4l959xHR7yfDntUvXENz35w9uGxUe/BwUfxggIhBKZpVoWSWMxoQsmyLNNsqAIrMBmNK9h2wzStmiLwTEYpM01TNy2rUdPEYlYqZs2K3LCbRrUiFjNSKacrvGU363pVYNJSMa/LnGlZLC+DWk1fjCT8aFiQVNtumpaVpFK+AE6l83YTWpZFpdJ+PLQcT9Yblm3bmWwhgIeDS5GaUbebsFBk0eAiGlzUqqsOhCwv4KElFG/9ZtlNWa4C3TAi8YTHh5AkDSE0LSsWJxAECy9FdMOwm5BYIREEw/GQomoQwlQ6h2JBBMF4QYAQMoUigmAoFszlGQghL4goHvKjwVQ6Z68LTLORzeUTSaJSrbYEZoNhCvFEkmXLELYuYFkuSRAMU3Acx7ZtnheSBJHN5e3Wa8qyQqysUDRtmqbjQE2rkBRNUrRhGI8FhlGPROI+BE0SlOM4pmUlEqQfxYOhRdOybLuZTmd8CIZhwepaCLk8gyAYgmCyLEMIWbaM4yFfAFlfSJSkYCjsD6DZXN5x4FpEup5K5yg6Q5KtLUzLymQYis4QJK3rumU3GaZIkimSpDVNs5vNElsmqTRB0JIkOQ7keYGk0iSZ4jnegVBRNYpK01SmWCg9vkCWNVXTVU3XNF2SKpJUWUd1DUWpoqo1VdMrFV2WV0VRU9TVFlaNFkqqoq6utbQyJ7OsyHGyIKq8XOWkSpFXZLUGFLUmy9X1UtTaf+F6/R9WFVXPF7hIjFihsrE4SVDZWFaMZYUEI8py7V9Rf1IX7W/kqQAAAABJRU5ErkJggg==" nextheight="444" nextwidth="963" class="image-node embed"><figcaption htmlattributes="[object Object]" class=""><a target="_blank" rel="noopener ugc nofollow noopener noopener" class="dont-break-out markup--anchor markup--figure-anchor" href="https://www.anrdoezrs.net/click-101540368-17083170">Contabo’s VPS</a> pricing</figcaption></figure><p>With my <a target="_blank" rel="noopener" class="dont-break-out markup--anchor markup--p-anchor" href="https://www.anrdoezrs.net/click-101540368-17083170">Contabo VPS</a>, I can run concurrent web scrapers and schedule them using cron jobs at different times. This approach helps prevent my IP from being flagged while also conserving RAM for my primary tasks.</p><h4 id="h-do-you-need-help-with-automation-web-scraping-ai-data-or-anything-that-my-laptop-can-deliver-feel-free-to-reach-me-on-upwork" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0"><strong><em>Do you need help with automation, web scraping, AI, data, or anything that my laptop can deliver? Feel free to reach me on Upwork! </em></strong><span data-name="man_technologist" class="emoji" data-type="emoji">👨‍💻</span></h4><div data-type="customButton" href="https://www.upwork.com/freelancers/~01185447baa36a1b77" class="center-contents"><a class="email-subscribe-button" href="https://www.upwork.com/freelancers/~01185447baa36a1b77">Let's build together!</a></div><hr><h2 id="h-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusion</h2><p>In this piece, we’ve covered the importance of Playwright headless browser for web scraping, and how it serves most of the web scraping tasks. Showing that you don’t need to learn multiple web scraping frameworks to build successful and performant crawlers.</p><p>Then we highlighted 5 different tips that <em>vibe coding</em> tools don’t tell you, but they make all the difference to turn you from a beginner to an advanced web scraping developer.</p><p>First, we discussed how to increase stealth and avoid being blocked by integrating Camoufox with Playwright.</p><p>Next, we looked at how intercepting HTTP responses before parsing HTML can save valuable time and help you capture hidden or critical data that might otherwise be missed.</p><p>We then examined how to handle infinite scroll pages efficiently using Playwright’s built-in functions, followed by strategies for optimizing data extraction with XPath or Playwright’s native selector capabilities.</p><p>Finally, we explored the differences between datacenter and residential proxies, highlighted the best options to start with, and explained how to integrate them effortlessly with Camoufox.</p><p>As demand for web scraping continues to grow, you can start applying these tips to land freelance projects on platforms like Upwork, build and monetize Apify actors for passive income, or simply create efficient crawlers for your own projects.</p><p>Perhaps this article will contribute to increasing even more the percentage of bots in internet traffic <span data-name="robot" class="emoji" data-type="emoji">🤖</span></p><p>Curious about what I’m building? <span data-name="eyes" class="emoji" data-type="emoji">👀</span></p><div data-type="subscribeButton" class="center-contents"><a class="email-subscribe-button" href="https://paragraph.com/@dadhalfdev/subscribe">Subscribe</a></div><br>]]></content:encoded>
            <author>dadhalfdev@newsletter.paragraph.com (Dad Half Dev)</author>
            <category>webscraping</category>
            <category>python</category>
            <category>programming</category>
        </item>
    </channel>
</rss>