<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ahmed Rehan</title>
    <description>The latest articles on Forem by Ahmed Rehan (@ar27111994).</description>
    <link>https://forem.com/ar27111994</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3678450%2F7fe013eb-7f8e-407a-8400-ac85724d8a4f.jpeg</url>
      <title>Forem: Ahmed Rehan</title>
      <link>https://forem.com/ar27111994</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ar27111994"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Ahmed Rehan</dc:creator>
      <pubDate>Thu, 22 Jan 2026 16:21:28 +0000</pubDate>
      <link>https://forem.com/ar27111994/-55k4</link>
      <guid>https://forem.com/ar27111994/-55k4</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/ar27111994/fixing-google-antigravity-pro-authentication-on-windows-10-wsl2-45jd" class="crayons-story__hidden-navigation-link"&gt;Fixing Google Antigravity Pro Authentication on Windows 10 + WSL2&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/ar27111994" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3678450%2F7fe013eb-7f8e-407a-8400-ac85724d8a4f.jpeg" alt="ar27111994 profile" class="crayons-avatar__image" width="460" height="460"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/ar27111994" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Ahmed Rehan
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Ahmed Rehan
                
              
              &lt;div id="story-author-preview-content-3188772" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/ar27111994" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3678450%2F7fe013eb-7f8e-407a-8400-ac85724d8a4f.jpeg" class="crayons-avatar__image" alt="" width="460" height="460"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Ahmed Rehan&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/ar27111994/fixing-google-antigravity-pro-authentication-on-windows-10-wsl2-45jd" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jan 21&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/ar27111994/fixing-google-antigravity-pro-authentication-on-windows-10-wsl2-45jd" id="article-link-3188772"&gt;
          Fixing Google Antigravity Pro Authentication on Windows 10 + WSL2
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/vibecoding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;vibecoding&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/linux"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;linux&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/antigravity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;antigravity&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/ar27111994/fixing-google-antigravity-pro-authentication-on-windows-10-wsl2-45jd" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;3&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/ar27111994/fixing-google-antigravity-pro-authentication-on-windows-10-wsl2-45jd#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>programming</category>
      <category>vibecoding</category>
      <category>linux</category>
      <category>antigravity</category>
    </item>
    <item>
      <title>Fixing Google Antigravity Pro Authentication on Windows 10 + WSL2</title>
      <dc:creator>Ahmed Rehan</dc:creator>
      <pubDate>Wed, 21 Jan 2026 17:33:30 +0000</pubDate>
      <link>https://forem.com/ar27111994/fixing-google-antigravity-pro-authentication-on-windows-10-wsl2-45jd</link>
      <guid>https://forem.com/ar27111994/fixing-google-antigravity-pro-authentication-on-windows-10-wsl2-45jd</guid>
      <description>&lt;p&gt;Google Antigravity is Google's new agent-first IDE that promises powerful AI-assisted development. However, getting the Pro features to work on Windows 10 with WSL2 (Ubuntu 24.04.3 LTS) can be challenging due to authentication issues. This comprehensive guide will walk you through every step needed to get your Pro/Ultra subscription working seamlessly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;When running Antigravity in WSL2, the authentication handshake between your Linux terminal and Windows browser often breaks or times out. This happens because WSL2 is a virtualized environment, and the redirect token struggles to find its way back to the WSL instance.&lt;/p&gt;

&lt;p&gt;Common symptoms include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browser opens but IDE stays on loading screen&lt;/li&gt;
&lt;li&gt;Browser Authentication is successful but the Agent Panel still says "Reqire Authentication" (or something similar), even though the &lt;code&gt;Antigravity Settings &amp;gt; Account&lt;/code&gt; Screen shows Account as already signed in.&lt;/li&gt;
&lt;li&gt;"Invalid Token" or "Login Expired" errors&lt;/li&gt;
&lt;li&gt;"Not Eligible" or "Unauthorized" messages&lt;/li&gt;
&lt;li&gt;Empty responses when running &lt;code&gt;agy&lt;/code&gt; commands&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting, ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows 10 with WSL2 installed&lt;/li&gt;
&lt;li&gt;Ubuntu 24.04.3 LTS (or similar)&lt;/li&gt;
&lt;li&gt;Google Antigravity installed on Windows&lt;/li&gt;
&lt;li&gt;A Google AI Pro or Ultra subscription using a personal Gmail account.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Fix the Silent Login Loop
&lt;/h2&gt;

&lt;p&gt;The first issue to address is WSL2's default NAT networking, which can hide the local ports Antigravity uses to listen for login signals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enable Mirrored Networking
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On Windows, navigate to &lt;code&gt;%USERPROFILE%&lt;/code&gt; (e.g., &lt;code&gt;C:\Users\YourName&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Create or edit a file named &lt;code&gt;.wslconfig&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add the following configuration:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[wsl2]&lt;/span&gt;
&lt;span class="py"&gt;networkingMode&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mirrored&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Restart WSL by opening PowerShell as Administrator and running:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--shutdown&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You may start getting this message on WSL Startup, especially on Windows 10 (shouldn't theoretically appear on Windows 11):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wsl: Mirrored networking mode is not supported: Windows version 19045.6466 does not have the required features.
Falling back to NAT networking.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In which case, you should remove the unsupported setting from your global config to get rid of the warning every time you boot/reboot and open Ubuntu, as WSL2 cannot enable this mode and defaults back to the standard NAT (Network Address Translation).&lt;/p&gt;

&lt;p&gt;Instead, you can try the following config to ensure that Agents always reliably reach local addresses (Supported on Windows 10):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[wsl2]&lt;/span&gt;
&lt;span class="py"&gt;localhostForwarding&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add or ensure these lines exist in &lt;code&gt;%USERPROFILE%\.wslconfig&lt;/code&gt;. Save and run &lt;code&gt;wsl --shutdown&lt;/code&gt; in your terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Synchronize Your System Clock
&lt;/h2&gt;

&lt;p&gt;Google's OAuth 2.0 authentication is highly sensitive to time drift. WSL2 clocks often drift when a laptop sleeps (like in my case), causing tokens to be rejected as expired.&lt;/p&gt;

&lt;p&gt;Run this in your Ubuntu terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ntpdate time.windows.com

&lt;span class="c"&gt;# If you don't have ntpdate installed:&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;util-linux-extra &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;hwclock &lt;span class="nt"&gt;-s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Try Authentication again
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;If GUI login continues to fail, manually Sign out from your account in the &lt;code&gt;Antigravity Settings &amp;gt; Account&lt;/code&gt; Screen.&lt;/li&gt;
&lt;li&gt;Close and Restart the IDE.&lt;/li&gt;
&lt;li&gt;Click on the &lt;code&gt;Google Sign in&lt;/code&gt; button in the top right and Authorize your Google AI Pro account.&lt;/li&gt;
&lt;li&gt;Close the Antigravity Sign-in confirmation page.&lt;/li&gt;
&lt;li&gt;If the issue persists, repeat the first step and continue reading below.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 4: Verify Account Eligibility
&lt;/h2&gt;

&lt;p&gt;Many authentication failures are actually due to account restrictions:&lt;/p&gt;

&lt;h3&gt;
  
  
  Account Type
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Personal accounts&lt;/strong&gt; (&lt;code&gt;@gmail.com&lt;/code&gt;) have the highest success rate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workspace accounts&lt;/strong&gt; may require admin approval for "Experimental Google AI Services"&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Regional Matching
&lt;/h3&gt;

&lt;p&gt;Ensure your Windows Region, Google Account Region, and IP address (no VPN) all match. Mismatched regions can cause silent authentication failures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Fix Missing WSL Extension Scripts
&lt;/h2&gt;

&lt;p&gt;A known bug in early Antigravity builds causes missing WSL helper scripts. Here's how to fix it:&lt;/p&gt;

&lt;h3&gt;
  
  
  Manual Script Extraction
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Download the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl" rel="noopener noreferrer"&gt;Remote - WSL extension&lt;/a&gt; from the VS Code Marketplace&lt;/li&gt;
&lt;li&gt;Click "Download VSIX" (downloads a &lt;code&gt;.vsix&lt;/code&gt; file) if in IDE extensions panel or use a tool like &lt;a href="https://cypherpunksamurai.github.io/vsix-downloader-webui/" rel="noopener noreferrer"&gt;VSIX Downloader&lt;/a&gt; for web download.&lt;/li&gt;
&lt;li&gt;Rename the file from &lt;code&gt;.vsix&lt;/code&gt; to &lt;code&gt;.zip&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open the zip and navigate to &lt;code&gt;extension/scripts/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Copy all files (especially &lt;code&gt;wslCode.sh&lt;/code&gt; and &lt;code&gt;wslDownload.sh&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Paste into: &lt;code&gt;%LOCALAPPDATA%\Programs\Antigravity\resources\app\extensions\antigravity-remote-wsl\scripts\&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Fix the Launcher ID
&lt;/h3&gt;

&lt;p&gt;Even with scripts present, you need to update the extension ID reference:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to &lt;code&gt;%LOCALAPPDATA%\Programs\Antigravity\bin\&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open the &lt;code&gt;antigravity&lt;/code&gt; file in Notepad&lt;/li&gt;
&lt;li&gt;Find: &lt;code&gt;WSL_EXT_ID="ms-vscode-remote.remote-wsl"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Change to: &lt;code&gt;WSL_EXT_ID="google.antigravity-remote-wsl"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Save and restart your WSL terminal&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Test WSL Sign In (Command Palette Method)
&lt;/h3&gt;

&lt;p&gt;Try Authentication in WSL:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Antigravity on Windows&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Ctrl + Shift + P&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Type "WSL" and select &lt;strong&gt;Remote-WSL: Connect to WSL&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The bottom-left corner should show &lt;code&gt;[WSL: Ubuntu]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Try signing in from this connected state&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 6: Create the WSL-to-Windows Bridge
&lt;/h2&gt;

&lt;p&gt;To use &lt;code&gt;agy&lt;/code&gt; commands from your Ubuntu terminal, you need to create a proper bridge to the Windows binary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create the Wrapper Script
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create the local bin directory:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.local/bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create the &lt;code&gt;agy&lt;/code&gt; wrapper (replace &lt;code&gt;[YOUR_WINDOWS_USERNAME]&lt;/code&gt; with your actual Windows username):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/.local/bin/agy &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
#!/usr/bin/env bash
# Robust wrapper to bridge WSL -&amp;gt; Windows CMD -&amp;gt; Antigravity
# REPLACE [YOUR_WINDOWS_USERNAME] with your actual folder name

WIN_USER="[YOUR_WINDOWS_USERNAME]"
WIN_PATH="C:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="sh"&gt;Users&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;WIN_USER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="sh"&gt;AppData&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="sh"&gt;Local&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="sh"&gt;Programs&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="sh"&gt;Antigravity&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="sh"&gt;bin&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="sh"&gt;antigravity.cmd"

# Call via cmd.exe to ensure Windows environment is initialized
# cd to C: drive to avoid UNC path warnings
cd /mnt/c &amp;amp;&amp;amp; cmd.exe /c "&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;WIN_PATH&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;" "&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="sh"&gt;"
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Make it executable:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ~/.local/bin/agy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add to your PATH:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.local/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export PATH="$HOME/.local/bin:$PATH"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verify Your Windows Username
&lt;/h3&gt;

&lt;p&gt;Before running the wrapper, verify your path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; /mnt/c/Users/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the &lt;code&gt;WIN_USER&lt;/code&gt; variable in the script to match exactly how your Windows username folder is spelled.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enable WSL Interoperability
&lt;/h3&gt;

&lt;p&gt;Ensure WSL can launch Windows processes by checking &lt;code&gt;/etc/wsl.conf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/wsl.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it doesn't exist or is empty, create it with these settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[interop]&lt;/span&gt;
&lt;span class="py"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;appendWindowsPath&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then restart WSL with &lt;code&gt;wsl --shutdown&lt;/code&gt; from PowerShell.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Verify Pro Authentication
&lt;/h2&gt;

&lt;p&gt;Once everything is set up, verify your CLI Setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check version&lt;/span&gt;
agy &lt;span class="nt"&gt;--version&lt;/span&gt;

&lt;span class="c"&gt;# List available commands&lt;/span&gt;
agy &lt;span class="nt"&gt;--help&lt;/span&gt;

&lt;span class="c"&gt;# Open IDE in current directory&lt;/span&gt;
agy &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now try signing in again to your Google account. The &lt;code&gt;Agent Panel&lt;/code&gt; should be available now, and the &lt;code&gt;Antigravity Settings &amp;gt; Account&lt;/code&gt; Screen shows Account as already signed in. Expected output for &lt;code&gt;Agent Panel&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tier:&lt;/strong&gt; Pro or Ultra&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; Gemini 3 Pro or Gemini 3 Flash, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Limit:&lt;/strong&gt; 1M+ tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Pro Agents
&lt;/h3&gt;

&lt;p&gt;Now you can invoke high-level agents directly on your WSL files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agy chat &lt;span class="s2"&gt;"Analyze the structure of this repo and suggest refactoring opportunities"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because you're authenticated as Pro, the agent will use the full index to understand your entire codebase structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting Quick Reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Issue&lt;/th&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;Browser opens, IDE stays loading&lt;/td&gt;
&lt;td&gt;Enable &lt;code&gt;networkingMode=mirrored&lt;/code&gt; in &lt;code&gt;.wslconfig&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clock Drift&lt;/td&gt;
&lt;td&gt;"Invalid Token" or "Login Expired"&lt;/td&gt;
&lt;td&gt;Run &lt;code&gt;sudo hwclock -s&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Account Type&lt;/td&gt;
&lt;td&gt;"Not Eligible"&lt;/td&gt;
&lt;td&gt;Use personal &lt;code&gt;@gmail.com&lt;/code&gt; account&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Missing Scripts&lt;/td&gt;
&lt;td&gt;IDE won't connect to WSL&lt;/td&gt;
&lt;td&gt;Download and extract scripts from VS Code Marketplace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wrong Extension ID&lt;/td&gt;
&lt;td&gt;Connection fails silently&lt;/td&gt;
&lt;td&gt;Update &lt;code&gt;WSL_EXT_ID&lt;/code&gt; in launcher script&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UNC Path Warnings&lt;/td&gt;
&lt;td&gt;Warnings in terminal output&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;cd /mnt/c &amp;amp;&amp;amp;&lt;/code&gt; in wrapper script&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Common Commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Open current directory in Antigravity&lt;/span&gt;
agy &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Check process usage and diagnostic information&lt;/span&gt;
agy &lt;span class="nt"&gt;--status&lt;/span&gt;

&lt;span class="c"&gt;# Check version&lt;/span&gt;
agy &lt;span class="nt"&gt;--version&lt;/span&gt;

&lt;span class="c"&gt;# Get help&lt;/span&gt;
agy &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pro Tips
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Persistent Sessions:&lt;/strong&gt; Enable "Persistent Agent" in Antigravity UI to keep agents running even if you close the terminal&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Project Indexing:&lt;/strong&gt; Let Antigravity fully index your project before asking complex questions for better results&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Token Limits:&lt;/strong&gt; Pro users get 1M+ token context windows, perfect for analyzing large codebases&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Regional Consistency:&lt;/strong&gt; Avoid using VPNs during authentication to prevent region mismatch issues&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Getting Google Antigravity Pro working on WSL2 requires bridging the gap between the Windows and Linux environments. By following these steps—fixing networking, synchronizing clocks, creating proper symlinks, and enabling interoperability—you'll unlock the full power of Google's agentic IDE.&lt;/p&gt;

&lt;p&gt;The effort is worth it: once configured, you'll have access to powerful AI agents that can understand and refactor your entire codebase, all while working seamlessly in your WSL2 development environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=example" rel="noopener noreferrer"&gt;Google Antigravity Setup Guide (Video)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl" rel="noopener noreferrer"&gt;VS Code Remote - WSL Extension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/wsl/" rel="noopener noreferrer"&gt;WSL2 Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Last updated: January 2026 | Tested on Windows 10 + WSL2 Ubuntu 24.04.3 LTS&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>vibecoding</category>
      <category>linux</category>
      <category>antigravity</category>
    </item>
    <item>
      <title>Stop paying for webhook debuggers. I built a better one (Open Source).</title>
      <dc:creator>Ahmed Rehan</dc:creator>
      <pubDate>Thu, 15 Jan 2026 13:40:27 +0000</pubDate>
      <link>https://forem.com/ar27111994/stop-paying-for-webhook-debuggers-i-built-a-better-one-open-source-dcl</link>
      <guid>https://forem.com/ar27111994/stop-paying-for-webhook-debuggers-i-built-a-better-one-open-source-dcl</guid>
      <description>&lt;h3&gt;
  
  
  The Struggle
&lt;/h3&gt;

&lt;p&gt;I remember the payment bug that kept me up until 3 AM.&lt;br&gt;
Stripe was sending a &lt;code&gt;invoice.payment_failed&lt;/code&gt; webhook, but only in production.&lt;br&gt;
I checked my logs: &lt;em&gt;Truncated&lt;/em&gt;.&lt;br&gt;
I checked my tunneling tool: &lt;em&gt;Session expired&lt;/em&gt;.&lt;br&gt;
I checked my SaaS bin: &lt;em&gt;History limit reached&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I realized I didn't have a debugging tool; I had a toy.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Solution: Webhook Debugger
&lt;/h3&gt;

&lt;p&gt;I decided to build my own solution. But I didn't just want a "bucket" that catches requests. I wanted to build a &lt;strong&gt;Reference Implementation&lt;/strong&gt; for how a modern, secure Node.js application should look in 2026.&lt;/p&gt;

&lt;p&gt;Here are the &lt;strong&gt;13 Engineering Patterns&lt;/strong&gt; I used to build it:&lt;/p&gt;
&lt;h4&gt;
  
  
  1. Global SSE Heartbeat &amp;amp; Padding 💓
&lt;/h4&gt;

&lt;p&gt;Most SSE implementations leak memory by creating a timer per connection.&lt;br&gt;
&lt;strong&gt;My Approach&lt;/strong&gt;: A single &lt;code&gt;setInterval&lt;/code&gt; iterates a &lt;code&gt;Set&lt;/code&gt; of clients.&lt;br&gt;
&lt;strong&gt;The Pro Tip&lt;/strong&gt;: I added &lt;code&gt;res.write(' '.repeat(2048))&lt;/code&gt; (2KB whitespace) and &lt;code&gt;X-Accel-Buffering: no&lt;/code&gt; headers. Why? Because corporate firewalls (and Nginx) love buffering streams. The padding forces them to flush the connection immediately.&lt;/p&gt;
&lt;h4&gt;
  
  
  2. SSRF Protection (DNS &amp;amp; IP Verification) 🛡️
&lt;/h4&gt;

&lt;p&gt;Allowing user-defined webhooks is dangerous (Server-Side Request Forgery).&lt;br&gt;
&lt;strong&gt;The Fix&lt;/strong&gt;: I wrote a custom validator in &lt;code&gt;src/utils/ssrf.js&lt;/code&gt; that resolves the DNS &lt;em&gt;before&lt;/em&gt; the request. It checks the IP against a blocklist of private ranges (RFC 1918) and cloud metadata services (&lt;code&gt;169.254.169.254&lt;/code&gt;). It even handles IPv4-mapped IPv6 addresses (&lt;code&gt;::ffff:127.0.0.1&lt;/code&gt;).&lt;/p&gt;
&lt;h4&gt;
  
  
  3. Deep Replay with Exponential Backoff 🔄
&lt;/h4&gt;

&lt;p&gt;Retrying a failed webhook isn't just "try again".&lt;br&gt;
&lt;strong&gt;The Logic&lt;/strong&gt;: If the destination yields a transient error (&lt;code&gt;ECONNABORTED&lt;/code&gt;, &lt;code&gt;503&lt;/code&gt;), the system waits 1s, then 2s, then 4s.&lt;br&gt;
&lt;strong&gt;Header Stripping&lt;/strong&gt;: The replay engine automatically strips sensitive headers (&lt;code&gt;Authorization&lt;/code&gt;, &lt;code&gt;Cookie&lt;/code&gt;) so you don't accidentally send production credentials to your local dev environment.&lt;/p&gt;
&lt;h4&gt;
  
  
  4. Timing-Safe Authentication ⏱️
&lt;/h4&gt;

&lt;p&gt;Never compare API keys with &lt;code&gt;===&lt;/code&gt;.&lt;br&gt;
&lt;strong&gt;The Attack&lt;/strong&gt;: An attacker can measure how long your server takes to say "No" to guess the key character-by-character.&lt;br&gt;
&lt;strong&gt;The Fix&lt;/strong&gt;: I use &lt;code&gt;crypto.timingSafeEqual&lt;/code&gt; in &lt;code&gt;src/utils/auth.js&lt;/code&gt; to ensure the comparison takes the exact same time whether the key is 99% correct or 0% correct.&lt;/p&gt;
&lt;h4&gt;
  
  
  5. Memory-Safe Rate Limiting (LRU) 🧠
&lt;/h4&gt;

&lt;p&gt;Standard rate limiters are often purely in-memory maps. If a botnet hits you with 1 million IPs, your server crashes (OOM).&lt;br&gt;
&lt;strong&gt;The Pattern&lt;/strong&gt;: My &lt;code&gt;RateLimiter&lt;/code&gt; uses a &lt;strong&gt;Sliding Window&lt;/strong&gt; with &lt;strong&gt;LRU Eviction&lt;/strong&gt;. It hard-caps at 1,000 entries. If the map is full, the oldest IP is evicted to make room. It prioritizes stability over strictness.&lt;/p&gt;
&lt;h4&gt;
  
  
  6. Memory-Safe Dataset Filtering 🔍
&lt;/h4&gt;

&lt;p&gt;Searching for a single timestamp in a 1GB JSON dataset will crash a standard Node.js process.&lt;br&gt;
&lt;strong&gt;The Solution&lt;/strong&gt;: Iterative Pagination. The &lt;code&gt;/replay&lt;/code&gt; endpoint reads chunks of 1000 items (&lt;code&gt;dataset.getData({ limit, offset })&lt;/code&gt;), searches for the event ID, and fetches the next chunk only if not found. This ensures we never load the entire dataset into memory.&lt;/p&gt;
&lt;h4&gt;
  
  
  7. Input Sanitization &amp;amp; Coercion 🧹
&lt;/h4&gt;

&lt;p&gt;Inputs from the wild are messy. Strings look like numbers; booleans look like strings.&lt;br&gt;
&lt;strong&gt;The Pattern&lt;/strong&gt;: A dedicated &lt;code&gt;coerceRuntimeOptions&lt;/code&gt; utility in &lt;code&gt;src/utils/config.js&lt;/code&gt; recursively walks the input object, coercing &lt;code&gt;"true"&lt;/code&gt; -&amp;gt; &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;"5"&lt;/code&gt; -&amp;gt; &lt;code&gt;5&lt;/code&gt;, ensuring the runtime configuration isn't crashed by type mismatches.&lt;/p&gt;
&lt;h4&gt;
  
  
  8. Index.html Caching 🚀
&lt;/h4&gt;

&lt;p&gt;We serve a UI, but we aren't a CDN.&lt;br&gt;
&lt;strong&gt;The Optimization&lt;/strong&gt;: The &lt;code&gt;index.html&lt;/code&gt; template is read from disk &lt;em&gt;once&lt;/em&gt; at startup and cached in a string variable (&lt;code&gt;indexTemplate&lt;/code&gt;). Placeholders like &lt;code&gt;{{VERSION}}&lt;/code&gt; are replaced on-the-fly using &lt;code&gt;escapeHtml()&lt;/code&gt;, but the disk I/O cost is paid only once.&lt;/p&gt;
&lt;h4&gt;
  
  
  9. Bootstrap Validation Logic 🩹
&lt;/h4&gt;

&lt;p&gt;What happens if the user manually edits the &lt;code&gt;INPUT.json&lt;/code&gt; and breaks the JSON syntax?&lt;br&gt;
&lt;strong&gt;Self-Healing&lt;/strong&gt;: The &lt;code&gt;ensureLocalInputExists&lt;/code&gt; function in &lt;code&gt;src/utils/bootstrap.js&lt;/code&gt; detects corrupt JSON on startup. Instead of crashing, it automatically renames the bad file to &lt;code&gt;.tmp&lt;/code&gt; and writes a fresh default configuration, logging a warning. The app &lt;em&gt;always&lt;/em&gt; starts.&lt;/p&gt;
&lt;h4&gt;
  
  
  10. Optimized Headers ⚡
&lt;/h4&gt;

&lt;p&gt;Every millisecond counts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Content-Encoding: identity&lt;/code&gt;: Disables gzip for the SSE stream (gzip buffers, which kills real-time).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cache-Control: no-cache&lt;/code&gt;: Forces browsers to verify the stream status.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Connection: keep-alive&lt;/code&gt;: Critical for long-lived streams.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  11. Testing Asynchronous Code 🧪
&lt;/h4&gt;

&lt;p&gt;Testing streaming and retries is notoriously hard.&lt;br&gt;
&lt;strong&gt;The Strategy&lt;/strong&gt;: We use &lt;code&gt;jest&lt;/code&gt; with custom helpers (&lt;code&gt;waitForCondition&lt;/code&gt; in &lt;code&gt;tests/helpers/test-utils.js&lt;/code&gt;) and mocked timers. In &lt;code&gt;resilience.test.js&lt;/code&gt;, we mock &lt;code&gt;axios&lt;/code&gt; to fail exactly twice with &lt;code&gt;ECONNABORTED&lt;/code&gt; to verify the retry logic attempts exactly 3 times before giving up.&lt;/p&gt;
&lt;h4&gt;
  
  
  12. Hot-Reloading (Zero Downtime Config) 🔥
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;: Restarting the server just to change the API key or add a webhook URL loses all SSE connections.&lt;br&gt;
&lt;strong&gt;The Solution&lt;/strong&gt;: A background poller in &lt;code&gt;src/main.js&lt;/code&gt; reads the &lt;code&gt;INPUT.json&lt;/code&gt; from the Key-Value Store every 5 seconds. When a change is detected:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It &lt;strong&gt;diffs&lt;/strong&gt; the new config against the old one.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;updates&lt;/strong&gt; middleware (body parser limits, rate limiter), auth keys, and webhook counts dynamically.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;reconciles&lt;/strong&gt; the webhook IDs: if the user increased &lt;code&gt;urlCount&lt;/code&gt;, new IDs are generated; if decreased, no IDs are removed to prevent data loss.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is all enabled by the &lt;code&gt;loggerMiddleware.updateOptions()&lt;/code&gt; function, which allows runtime reconfiguration of the logger instance.&lt;/p&gt;
&lt;h4&gt;
  
  
  13. Escape the "SaaS Tax" (Self-Hosting) 💸
&lt;/h4&gt;

&lt;p&gt;If you are an agency handling 50 clients, paying $30/mo per seat for debugging tools adds up.&lt;br&gt;
Since this is a standard &lt;strong&gt;Dockerized Node.js app&lt;/strong&gt;, you can deploy it to your own generic VPS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; apify/actor-node:20&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; npm start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/ar27111994/webhook-debugger-logger" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;&lt;/strong&gt; (v2.8.7 is out now!)&lt;/p&gt;




</description>
      <category>webhooks</category>
      <category>opensource</category>
      <category>javascript</category>
      <category>tooling</category>
    </item>
    <item>
      <title>How to Debug Webhook Integrations in Minutes (Step-by-Step Guide)</title>
      <dc:creator>Ahmed Rehan</dc:creator>
      <pubDate>Thu, 25 Dec 2025 15:15:33 +0000</pubDate>
      <link>https://forem.com/ar27111994/how-to-debug-webhook-integrations-in-minutes-step-by-step-guide-3ccf</link>
      <guid>https://forem.com/ar27111994/how-to-debug-webhook-integrations-in-minutes-step-by-step-guide-3ccf</guid>
      <description>&lt;p&gt;Debugging webhooks is painful. You can't see what's being sent, signature verification fails mysteriously, and testing edge cases requires complex setups.&lt;/p&gt;

&lt;p&gt;In this tutorial, I'll show you how to debug webhook integrations in minutes using Webhook Debugger &amp;amp; Logger.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Accomplish
&lt;/h2&gt;

&lt;p&gt;By the end of this tutorial, you'll:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Capture webhook requests from any service (Stripe, Shopify, etc.)&lt;/li&gt;
&lt;li&gt;✅ Use &lt;strong&gt;"Launch Packs"&lt;/strong&gt; for instant, pre-configured setup&lt;/li&gt;
&lt;li&gt;✅ Inspect headers, body, and metadata in real-time&lt;/li&gt;
&lt;li&gt;✅ Verify signatures with &lt;strong&gt;Raw Request Data&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;✅ Replay requests to test idempotency&lt;/li&gt;
&lt;li&gt;✅ Secure your logs with &lt;strong&gt;CIDR/Bearer Auth&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⏱️ &lt;strong&gt;Time required:&lt;/strong&gt; ~10 minutes&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Free Apify account (sign up with email or GitHub)&lt;/li&gt;
&lt;li&gt;A service that sends webhooks (Stripe, GitHub, Shopify, etc.)&lt;/li&gt;
&lt;li&gt;No coding required for basic usage&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What You'll Achieve
&lt;/h2&gt;

&lt;p&gt;By the end, you'll have a complete webhook debugging workflow that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Captures every incoming request&lt;/li&gt;
&lt;li&gt;Shows raw data for signature debugging&lt;/li&gt;
&lt;li&gt;Allows you to replay requests for testing&lt;/li&gt;
&lt;li&gt;Exports logs as JSON/CSV&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Real example: I debugged a Stripe payment webhook in 8 minutes using this approach. Previously took me 3+ hours.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Access Webhook Debugger &amp;amp; Logger
&lt;/h2&gt;

&lt;p&gt;Go to the &lt;a href="https://apify.com/ar27111994/webhook-debugger-logger" rel="noopener noreferrer"&gt;Webhook Debugger page&lt;/a&gt; on Apify Store.&lt;/p&gt;

&lt;p&gt;If you don't have an Apify account:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click "Try for free"&lt;/li&gt;
&lt;li&gt;Sign up with email or GitHub (takes 30 seconds)&lt;/li&gt;
&lt;li&gt;You'll be redirected to Apify Console&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What to expect:&lt;/strong&gt; You'll see the Actor's input configuration page.&lt;/p&gt;

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




&lt;h2&gt;
  
  
  Step 2: Configure Basic Settings
&lt;/h2&gt;

&lt;p&gt;You'll see the input form with these key fields:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;URL Count&lt;/strong&gt; (required)
&lt;/h3&gt;

&lt;p&gt;How many webhook URLs to generate (1-10)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"urlCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example: If you're testing Stripe payments, GitHub webhooks, and Shopify orders, set this to 3.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Launch Pack Settings&lt;/strong&gt; (v2.7.0 Optimized)
&lt;/h3&gt;

&lt;p&gt;Choose a pre-configured scenario for your stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shopify Launch Pack&lt;/strong&gt;: 72h retention + sub-10ms logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stripe Hardening Pack&lt;/strong&gt;: RAW body capture for signature validation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slack Block Kit&lt;/strong&gt;: Interaction mocking and payload validation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Basic configuration example:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"urlCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"retentionHours"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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




&lt;h2&gt;
  
  
  Step 3: Advanced Configuration (Optional)
&lt;/h2&gt;

&lt;p&gt;For more control, expand the advanced settings:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Max Payload Size&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Maximum request body size (default: 10MB)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxPayloadSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10485760&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Enable JSON Parsing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Automatically parse JSON payloads (default: true)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"enableJSONParsing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;JSON Schema Validation&lt;/strong&gt; (v2.0+)
&lt;/h3&gt;

&lt;p&gt;Reject invalid payloads automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"jsonSchema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"number"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; Testing API integrations that must conform to a specific payload structure.&lt;/p&gt;

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




&lt;h2&gt;
  
  
  Step 4: Run the Actor
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Click the &lt;strong&gt;"Start"&lt;/strong&gt; button&lt;/li&gt;
&lt;li&gt;Status changes to &lt;strong&gt;"Running"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Typically takes 5-10 seconds to spin up&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;⚠️ Tip:&lt;/strong&gt; You can close the page - the Actor continues running in the background.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's happening:&lt;/strong&gt; The Actor is starting a serverless container and generating your webhook URLs.&lt;/p&gt;

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




&lt;h2&gt;
  
  
  Step 5: Get Your Webhook URLs
&lt;/h2&gt;

&lt;p&gt;Once running, there are two ways to get your URLs:&lt;/p&gt;

&lt;h3&gt;
  
  
  Method 1: Live View
&lt;/h3&gt;

&lt;p&gt;Click &lt;strong&gt;"Live View"&lt;/strong&gt; tab to see the web interface with your URLs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method 2: Key-Value Store
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Storage&lt;/strong&gt; → &lt;strong&gt;Key-value stores&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Look for &lt;strong&gt;"WEBHOOK_STATE"&lt;/strong&gt; key&lt;/li&gt;
&lt;li&gt;You'll see your webhook IDs&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  URL Format
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://&amp;lt;actor-run-id&amp;gt;.runs.apify.net/webhook/&amp;lt;webhook-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://abc123xyz.runs.apify.net/webhook/wh_abc123
https://abc123xyz.runs.apify.net/webhook/wh_def456
https://abc123xyz.runs.apify.net/webhook/wh_ghi789
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;💡 Pro tip:&lt;/strong&gt; Bookmark these URLs for the duration of your testing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Configure Your Service
&lt;/h2&gt;

&lt;p&gt;Now configure your webhook source (Stripe, GitHub, etc.) to send to your URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Stripe
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to Stripe Dashboard → Developers → Webhooks&lt;/li&gt;
&lt;li&gt;Click "Add endpoint"&lt;/li&gt;
&lt;li&gt;Paste your webhook URL: &lt;code&gt;https://&amp;lt;run-id&amp;gt;.runs.apify.net/webhook/wh_abc123&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select events (e.g., &lt;code&gt;payment_intent.succeeded&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example: GitHub
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to Repository → Settings → Webhooks&lt;/li&gt;
&lt;li&gt;Click "Add webhook"&lt;/li&gt;
&lt;li&gt;Paste your URL&lt;/li&gt;
&lt;li&gt;Select events (e.g., &lt;code&gt;push&lt;/code&gt;, &lt;code&gt;pull_request&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What happens next:&lt;/strong&gt; Any webhook sent to this URL will be captured and logged.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7: Trigger a Test Webhook
&lt;/h2&gt;

&lt;p&gt;There are two ways to test:&lt;/p&gt;

&lt;h3&gt;
  
  
  Method 1: Service Test Button
&lt;/h3&gt;

&lt;p&gt;Most services have a "Send test webhook" button. Use it!&lt;/p&gt;

&lt;h3&gt;
  
  
  Method 2: Manual cURL
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://&amp;lt;run-id&amp;gt;.runs.apify.net/webhook/wh_abc123 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"event": "payment.success", "userId": "user_123", "amount": 9999}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What you'll see:&lt;/strong&gt; Request appears in the Dataset within 1-2 seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 8: View Results in Real-Time
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Option 1: Dataset Tab
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Storage&lt;/strong&gt; → &lt;strong&gt;Dataset&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;See all captured requests&lt;/li&gt;
&lt;li&gt;Click any item to see full details&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Option 2: Real-time Streaming (Advanced)
&lt;/h3&gt;

&lt;p&gt;Use Server-Sent Events (SSE) for live monitoring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-N&lt;/span&gt; https://&amp;lt;run-id&amp;gt;.runs.apify.net/log-stream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What You'll See
&lt;/h3&gt;

&lt;p&gt;Each captured request includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-12-25T14:31:45Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"webhookId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wh_abc123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"content-type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"user-agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Stripe/1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"stripe-signature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"t=1735137105,v1=abc123..."&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;payment.success&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;amount&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: 9999}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"queryParams"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;78&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"contentType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"processingTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"remoteIp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"54.187.174.169"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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




&lt;h2&gt;
  
  
  Step 9: Debug Signature Verification
&lt;/h2&gt;

&lt;p&gt;This is where raw data access becomes crucial.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;Signature verification fails because you're comparing the signature against the PARSED JSON, not the raw bytes.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution
&lt;/h3&gt;

&lt;p&gt;Use the captured raw body:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="c1"&gt;// From Webhook Debugger logs:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rawBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{"type": "payment.success", "amount": 9999}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;t=1735137105,v1=abc123...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// from stripe-signature header&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;whsec_yourStripeSecret&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Extract timestamp and signature&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// Compute expected signature&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rawBody&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hmac&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expectedSignature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Verify&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isValid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timingSafeEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expectedSignature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Signature valid:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;💡 Key insight:&lt;/strong&gt; You MUST use the raw body from the logs, not your parsed JSON object.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 10: Test Idempotency with Replay
&lt;/h2&gt;

&lt;p&gt;Use the &lt;code&gt;/replay&lt;/code&gt; API to test duplicate event handling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://&amp;lt;run-id&amp;gt;.runs.apify.net/replay/wh_abc123 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "destination": "https://myapp.com/webhook",
    "headers": {
      "X-Test-Replay": "true"
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This resends the captured webhook to your destination, allowing you to verify that your app handles duplicates correctly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 11: Export and Analyze
&lt;/h2&gt;

&lt;p&gt;Export your logs for further analysis:&lt;/p&gt;

&lt;h3&gt;
  
  
  Via Console:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Storage&lt;/strong&gt; → &lt;strong&gt;Dataset&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"Export"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Choose format (JSON, CSV, Excel)&lt;/li&gt;
&lt;li&gt;Download&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Via API:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.apify.com/v2/datasets/&amp;lt;dataset-id&amp;gt;/items?format=json&amp;amp;clean=1"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &amp;lt;your-api-token&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use cases for exported data:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Share with team members&lt;/li&gt;
&lt;li&gt;Import into analytics tools&lt;/li&gt;
&lt;li&gt;Create custom reports&lt;/li&gt;
&lt;li&gt;Archive for compliance&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Pro Tips for Better Results
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Use Specific Webhook IDs
&lt;/h3&gt;

&lt;p&gt;Create different IDs for different services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;wh_stripe&lt;/code&gt; for Stripe&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;wh_github&lt;/code&gt; for GitHub&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;wh_shopify&lt;/code&gt; for Shopify&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Filter Logs
&lt;/h3&gt;

&lt;p&gt;Use query parameters to filter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/logs?webhookId&lt;span class="o"&gt;=&lt;/span&gt;wh_stripe&amp;amp;method&lt;span class="o"&gt;=&lt;/span&gt;POST&amp;amp;statusCode&lt;span class="o"&gt;=&lt;/span&gt;200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Force Status Codes
&lt;/h3&gt;

&lt;p&gt;Test error handling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;https://&amp;lt;run-id&amp;gt;.runs.apify.net/webhook/wh_abc123?__status&lt;span class="o"&gt;=&lt;/span&gt;500
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Simulate Latency (v2.0+)
&lt;/h3&gt;

&lt;p&gt;Test timeout handling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customResponseDelay"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;second&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;delay&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue: "Webhook not found or expired"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Check that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The webhook ID is correct&lt;/li&gt;
&lt;li&gt;The Actor is still running&lt;/li&gt;
&lt;li&gt;The retention period hasn't expired&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Use &lt;code&gt;/info&lt;/code&gt; endpoint to verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://&amp;lt;run-id&amp;gt;.runs.apify.net/info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Issue: Requests not appearing
&lt;/h3&gt;

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

&lt;ol&gt;
&lt;li&gt;Verify the URL is correct&lt;/li&gt;
&lt;li&gt;Check that the Actor is in "Running" state&lt;/li&gt;
&lt;li&gt;Ensure the service is actually sending webhooks&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Issue: JSON parsing errors
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Check the &lt;code&gt;enableJSONParsing&lt;/code&gt; setting and verify the payload is valid JSON.&lt;/p&gt;




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

&lt;p&gt;You now have a complete webhook debugging workflow! 🎉&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you learned:&lt;/strong&gt;&lt;br&gt;
✅ How to capture webhooks without localhost tunneling&lt;br&gt;
✅ How to inspect raw request data for signature debugging&lt;br&gt;
✅ How to replay webhooks to test idempotency&lt;br&gt;
✅ How to export and analyze webhook logs&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time saved:&lt;/strong&gt; What used to take 3-4 hours now takes 10-15 minutes.&lt;/p&gt;

&lt;p&gt;Try Webhook Debugger yourself: &lt;a href="https://apify.com/ar27111994/webhook-debugger-logger" rel="noopener noreferrer"&gt;https://apify.com/ar27111994/webhook-debugger-logger&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Questions?&lt;/strong&gt; Drop them in the comments! 👇&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;👍 If this tutorial helped you, please give it a like and follow for more webhook debugging tips!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>webhooks</category>
      <category>api</category>
      <category>debugging</category>
    </item>
    <item>
      <title>The 6 Best Webhook Testing Tools for Developers in 2025</title>
      <dc:creator>Ahmed Rehan</dc:creator>
      <pubDate>Thu, 25 Dec 2025 15:09:49 +0000</pubDate>
      <link>https://forem.com/ar27111994/the-6-best-webhook-testing-tools-for-developers-in-2025-1o0i</link>
      <guid>https://forem.com/ar27111994/the-6-best-webhook-testing-tools-for-developers-in-2025-1o0i</guid>
      <description>&lt;p&gt;Webhooks power modern web apps, but when they fail, debugging becomes a nightmare. After testing dozens of tools while building integrations for Stripe, GitHub, and Shopify, here are the 6 best webhook testing tools for developers in 2025.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🥇 &lt;strong&gt;Best overall&lt;/strong&gt;: Webhook Debugger &amp;amp; Logger (pay-per-event, great features)&lt;/li&gt;
&lt;li&gt;🏠 &lt;strong&gt;Best for localhost&lt;/strong&gt;: ngrok (tunneling classic)&lt;/li&gt;
&lt;li&gt;🎯 &lt;strong&gt;Best for quick tests&lt;/strong&gt;: Webhook.site (free, simple)&lt;/li&gt;
&lt;li&gt;🏢 &lt;strong&gt;Best for enterprise&lt;/strong&gt;: Hookdeck (production-grade, expensive)&lt;/li&gt;
&lt;li&gt;💰 &lt;strong&gt;Best free option&lt;/strong&gt;: RequestBin (basic but gets the job done)&lt;/li&gt;
&lt;li&gt;🎭 &lt;strong&gt;Best for mocking&lt;/strong&gt;: Beeceptor (custom API responses)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What I Looked For
&lt;/h2&gt;

&lt;p&gt;Before diving in, here's what matters when choosing a webhook testing tool:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt; - How fast can you start capturing webhooks?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of integration&lt;/strong&gt; - Simple setup or complex configuration?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt; - Clear docs make or break dev experience&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pricing&lt;/strong&gt; - Free tier? Subscription? Pay-per-use?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community/Support&lt;/strong&gt; - Active development and responsive support?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let's look at each tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. 🥇 Webhook Debugger &amp;amp; Logger
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Link:&lt;/strong&gt; &lt;a href="https://apify.com/ar27111994/webhook-debugger-logger" rel="noopener noreferrer"&gt;https://apify.com/ar27111994/webhook-debugger-logger&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Pricing:&lt;/strong&gt; $10/1,000 webhooks (pay-per-event)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Quick start difficulty:&lt;/strong&gt; Easy ✅&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;br&gt;
A serverless Apify Actor designed specifically for webhook debugging. Generates temporary webhook URLs and logs every incoming request with complete metadata.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key features:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;✅ CIDR IP Whitelisting &amp;amp; Bearer Auth 🛡️
✅ Sensitive Header Masking (Auth/Key scrubbing)
✅ Real-time request capture (SSE Stream)
✅ No localhost tunnelling needed
✅ /replay API for testing idempotency
✅ JSON Schema validation
✅ Custom status codes &amp;amp; latency simulation (Standby Mode)
✅ Export as JSON/CSV
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Developer experience highlights:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zero setup - start capturing in 30 seconds&lt;/li&gt;
&lt;li&gt;Complete raw data access (crucial for signature debugging)&lt;/li&gt;
&lt;li&gt;Programmatic API for CI/CD integration&lt;/li&gt;
&lt;li&gt;Enterprise features (IP whitelisting, API key auth)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Launch Week Survival&lt;/strong&gt;: Handling burst traffic for high-stakes releases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stripe &amp;amp; Shopify integrations&lt;/strong&gt;: Using pre-configured "Launch Packs."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing signature verification&lt;/strong&gt;: Accessing raw request bodies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise Security&lt;/strong&gt;: CIDR whitelisting and header scrubbing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API mocking&lt;/strong&gt;: Simulating slow or faulty 3rd party APIs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Code example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start Actor and get webhook URL&lt;/span&gt;
&lt;span class="c"&gt;# https://&amp;lt;run-id&amp;gt;.runs.apify.net/webhook/wh_abc123&lt;/span&gt;

&lt;span class="c"&gt;# Send test webhook&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://&amp;lt;run-id&amp;gt;.runs.apify.net/webhook/wh_abc123 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"event": "payment.success", "amount": 9999}'&lt;/span&gt;

&lt;span class="c"&gt;# Replay captured webhook&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://&amp;lt;run-id&amp;gt;.runs.apify.net/replay/wh_abc123 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"destination": "https://myapp.com/webhook"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Pay only for what you use&lt;/li&gt;
&lt;li&gt;Advanced features (replay, mocking, validation)&lt;/li&gt;
&lt;li&gt;Persistent URLs (1-72 hours configurable)&lt;/li&gt;
&lt;li&gt;No tunnelling complexity&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Requires Apify account (free tier available)&lt;/li&gt;
&lt;li&gt;Not as well-known as ngrok&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. 🏠 ngrok
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Link:&lt;/strong&gt; &lt;a href="https://ngrok.com" rel="noopener noreferrer"&gt;https://ngrok.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Pricing:&lt;/strong&gt; Free / $8/month (Basic) / $20/month (Pro)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Quick start difficulty:&lt;/strong&gt; Moderate&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;br&gt;
Creates secure tunnels to expose your localhost to the internet. The gold standard for local webhook development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best feature:&lt;/strong&gt; Request inspection with replay&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install ngrok&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;ngrok

&lt;span class="c"&gt;# Start tunnel to localhost:3000&lt;/span&gt;
ngrok http 3000

&lt;span class="c"&gt;# Get public URL like: https://abc123.ngrok.io&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Industry standard&lt;/li&gt;
&lt;li&gt;Robust and reliable&lt;/li&gt;
&lt;li&gt;Request inspection included&lt;/li&gt;
&lt;li&gt;Replay functionality&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Free URLs change every session&lt;/li&gt;
&lt;li&gt;Requires CLI installation&lt;/li&gt;
&lt;li&gt;Monthly subscription for persistent URLs&lt;/li&gt;
&lt;li&gt;Focused on tunnelling, not debugging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Local development when you need webhooks to hit your localhost server.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. 🎯 Webhook.site
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Link:&lt;/strong&gt; &lt;a href="https://webhook.site" rel="noopener noreferrer"&gt;https://webhook.site&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Pricing:&lt;/strong&gt; Free (limited) / $10/month (Pro)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Quick start difficulty:&lt;/strong&gt; Easy ✅&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;br&gt;
Instant webhook URLs for quick inspections. No account needed (free tier).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best feature:&lt;/strong&gt; Instant setup - open site, get URL&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Zero setup on free tier&lt;/li&gt;
&lt;li&gt;Clean, simple UI&lt;/li&gt;
&lt;li&gt;Good for quick tests&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Some features require Custom Actions (paid)&lt;/li&gt;
&lt;li&gt;Subscription-based pricing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; One-off tests when you just need to see what's being sent.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. 🏢 Hookdeck
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Link:&lt;/strong&gt; &lt;a href="https://hookdeck.com" rel="noopener noreferrer"&gt;https://hookdeck.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Pricing:&lt;/strong&gt; Free tier / $70/month (Pro)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Quick start difficulty:&lt;/strong&gt; Complex&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;br&gt;
Enterprise webhook management platform with routing, retries, and transformation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best feature:&lt;/strong&gt; Production-grade reliability with automatic retries&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Built for production scale&lt;/li&gt;
&lt;li&gt;Automatic retries and error handling&lt;/li&gt;
&lt;li&gt;Payload transformation&lt;/li&gt;
&lt;li&gt;Extensive logging&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Expensive ($70/month minimum)&lt;/li&gt;
&lt;li&gt;Overkill for simple debugging&lt;/li&gt;
&lt;li&gt;Complex setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Enterprise teams managing thousands of webhooks daily.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. 💰 RequestBin
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Link:&lt;/strong&gt; &lt;a href="https://requestbin.com" rel="noopener noreferrer"&gt;https://requestbin.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Pricing:&lt;/strong&gt; Free (hosted) / Self-hosted&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Quick start difficulty:&lt;/strong&gt; Easy ✅&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;br&gt;
Creates temporary bins to capture HTTP requests. Minimalist and straightforward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best feature:&lt;/strong&gt; Completely free, no account required&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Free (hosted version)&lt;/li&gt;
&lt;li&gt;Open source&lt;/li&gt;
&lt;li&gt;Simple interface&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;URLs expire quickly (20 requests or 48 hours)&lt;/li&gt;
&lt;li&gt;Very basic features&lt;/li&gt;
&lt;li&gt;No replay or mocking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Simple, disposable testing.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. 🎭 Beeceptor
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Link:&lt;/strong&gt; &lt;a href="https://beeceptor.com" rel="noopener noreferrer"&gt;https://beeceptor.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Pricing:&lt;/strong&gt; Free tier / $10/month (Pro)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Quick start difficulty:&lt;/strong&gt; Easy&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;br&gt;
Mock API endpoints with custom responses. Useful for testing client behaviour.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best feature:&lt;/strong&gt; Custom response rules&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Great for API mocking&lt;/li&gt;
&lt;li&gt;Custom responses&lt;/li&gt;
&lt;li&gt;Request logging&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Not webhook-specific&lt;/li&gt;
&lt;li&gt;Limited free tier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; API mocking when you need custom responses.&lt;/p&gt;




&lt;h2&gt;
  
  
  Comparison Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Webhook Debugger&lt;/th&gt;
&lt;th&gt;ngrok&lt;/th&gt;
&lt;th&gt;Webhook.site&lt;/th&gt;
&lt;th&gt;Hookdeck&lt;/th&gt;
&lt;th&gt;RequestBin&lt;/th&gt;
&lt;th&gt;Beeceptor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Replay&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mocking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Schema Validation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅*&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;URL Duration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1-72h&lt;/td&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;td&gt;168h (7 days)&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;td&gt;48h&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API Access&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Free Tier&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price (Paid)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$10/1k events&lt;/td&gt;
&lt;td&gt;$8/mo&lt;/td&gt;
&lt;td&gt;$9/mo&lt;/td&gt;
&lt;td&gt;$70/mo&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;$10/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;*Via Custom Actions&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  My Recommendation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;For most developers:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Webhook Debugger &amp;amp; Logger offers the best balance. Pay-per-event pricing means you only pay for what you use, and features like replay, mocking, and schema validation make serious debugging possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For local development:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
ngrok is still the go-to when you need localhost exposure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For quick tests:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Webhook.site or RequestBin work fine for simple inspections.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For enterprise:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Hookdeck provides production reliability at enterprise pricing.&lt;/p&gt;




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

&lt;p&gt;I personally saved 10+ hours per week switching to Webhook Debugger for Stripe and GitHub integrations. The ability to replay requests and validate schemas automatically has been a game-changer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What webhooks are you debugging?&lt;/strong&gt; Drop a comment! 💬&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>api</category>
      <category>tooling</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
