DEV Community

Cover image for Learning ngrok: Inspect and Replay
Scott McAllister
Scott McAllister

Posted on • Updated on

Learning ngrok: Inspect and Replay

My first post on, written back in 2019, was about creating a local web server using Python and ngrok. Little did I know that four years later I would be an crew member on the rocket ship that is ngrok.

I joined the company a couple weeks ago, and I'm in the middle of ramping up with the organization and learning more about the product. While I explore the features that are new to me I'm going to write about things I learn that may be valuable to the community. This post is going to cover the Inspect and Replay feature.

A popular use case of ngrok is to receive webhooks on your local machine. As explained in the post I mentioned above, you can spin up a lightweight web server and run ngrok http 80 on your command line to provide a destination for incoming webhooks to land. For this exercise, I wrote the following code in Go to receive webhooks at the root endpoint of the domain.

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Printf("Webhook: %v", r)

    port := ":80"
    err := http.ListenAndServe(port, nil)
    if err != nil {
Enter fullscreen mode Exit fullscreen mode

The server is listening for requests on port 80, and prints the raw http.Request which ends up looking something like this for a webhook received from PagerDuty.

Webhook: &{POST / HTTP/1.1 1 1 map[Accept:[application/json]
 Accept-Encoding:[gzip] Content-Length:[1438] Content-Type:[application/json] User-Agent:[PagerDuty-Webhook/V3.0] 
X-Forwarded-For:[] X-Forwarded-Proto:[https] 
X-Webhook-Subscription:[PXXXXX]] 0x140001582c0 <nil> 1438 
[] false map[] map[] <nil> 
map[] [::1]:57318 / <nil> <nil> <nil> 0x14000158300}
Enter fullscreen mode Exit fullscreen mode

There is definitely more I could do to my code to get a better view of the incoming webhook. However, it appears ngrok already does a lot of that for us out the box. I've recently discovered the ngrok inspector. It can be accessed while ngrok is running by opening http://localhost:4040/ where you're shown a view like this.

Screenshot of ngrok inspector

All the HTTP requests are listed down the left side, and on right is a nicely formatted representation of the webhook JSON payload. There are also tabs to look at the Headers, the Raw request, and even the Binary (though, I'm not entirely sure why I would want that :thinking_face: If you know, please share in the comments).

There's also a Replay button that not only lets me replay the selected HTTP request, but you can also choose to modify the replayed request. For example, in my current situation I'm consuming webhooks from PagerDuty incidents. The webhooks are fired depending on whether the state of an incident changes. Some examples of incident state include triggered, acknowledged, and resolved. If my code that's consuming these webhooks behaves differently depending on what type of action occurring on the incident then to speed up my debugging I could select Replay with Modifications.

Screenshot of the Replay with Modifications button in the ngrok inspector

Find the event_type in the JSON body of the request and change it from incident.triggered to incident.acknowledged and click Replay.

Screenshot of request modification window in the ngrok inspector

That seems pretty handy. I could see myself using that in the future. Hopefully you found this useful. If you have any questions or constructive suggestions please feel free to leave a comment.

Top comments (0)