Instagram DM webhook verified and subscribed, but real DMs never reach n8n (curl works)

Instagram DMs never reach my n8n webhook, even though the webhook is verified in Meta, the messages field is subscribed, and a manual curl to the same URL runs the workflow perfectly. WhatsApp works fine in the same workflow — only Instagram fails. My setup is a Webhook node on POST with path instagram-dm in a published workflow, running n8n in Docker on Windows 11 tunnelled through cloudflared. The Meta app uses the Instagram use case with Instagram Login and is in published state. The webhook verified successfully and step 3 shows green, the messages field is subscribed in the Webhook fields table, and the account-level webhook subscription is toggled On in step 2. Both the business account and the sending account are accepted Instagram Testers, and the business account is logged out everywhere. Meta’s Test button for the messages field triggers the workflow correctly, and a manual curl -X POST to the production webhook URL returns {“message”:“Workflow was started”} with the full workflow running in under 4 seconds. But real DMs from the tester account produce nothing at all — no execution appears, and nothing shows in docker logs, not even an “unknown webhook” line. Earlier I had a second Webhook node on GET using the same path to answer Meta’s verification challenge, and the logs showed “This webhook is not registered for GET requests” alongside “Received request for unknown webhook: The requested webhook instagram-dm is not registered”. I deleted the GET node and the POST path registered correctly, which curl confirms, but real DMs still never arrive. Is there anything beyond webhook verification and field subscription that gates real Instagram message delivery in development mode, and is there a supported way to serve both the GET verification challenge and POST messages on a single path in n8n?

Hey @Gio_Saliba, while you wait for a response, here are some things that might help:

Suggested resources

Automatically matched to your question.

Docs:

Forum:

@CameronDWills, @marioja, @Delfin_Cortes - you’ve helped with similar issues before, can you take a look?

Automatically suggested by n8n’s community bot. It’s a pilot - please share feedback here.

Hi @Gio_Saliba Welcome to the n8n community
i would say nothing in the docker logs is the useful clue. Meta isn’t sending the request at all, so every dashboard-side thing you’ve checked is fine and the gate is on the Instagram account itself. In the Instagram app, go to Settings and privacy, Messages and story replies, Message controls, and turn on Allow Access to Messages under Connected tools. It lives outside the developer dashboard, the Test button ignores it, and if the account authorised your app before it was on, you have to reconnect for it to take.

For one path serving both verbs, open the Webhook node’s Settings tab and switch on Allow Multiple HTTP Methods. HTTP Method becomes a multi-select and you tick GET and POST, no second node.

Let me know if this helps

Hi @Gio_Saliba

Your n8n webhook, Docker setup, Cloudflared tunnel, and POST registration are working correctly. Manual curl requests and Meta’s test event reach the published workflow, while real Instagram DMs generate no inbound request or execution. This means the failure occurs upstream of n8n, rather than in the workflow or tunnel.

Development mode does restrict Instagram Messaging webhooks to app-role users, and Meta requires the receiving Professional account to be authorized with the correct Instagram Login permissions, especially instagram_business_manage_messages. Since both accounts are accepted testers and the account-level subscription is enabled, the remaining likely cause is a Meta-side messages delivery or fan-out issue affecting the Instagram Login integration.

Verify the receiving account’s current token permissions and subscription directly with the Graph API. Confirm that GET /{IG_USER_ID}/subscribed_apps returns messages, reauthorize the receiving account, check Instagram’s Connected Tools setting, and repeat a fresh tester-to-tester DM test while monitoring Cloudflared access logs. If no request appears, report the issue to Meta with timestamps and evidence that dashboard tests work but real DMs never reach the endpoint.

A single n8n Webhook node does not reliably act as both GET and POST for the same path. The supported design is to handle the GET verification challenge in a Cloudflare Worker, reverse proxy, or small external endpoint, then forward POST requests to n8n’s production webhook. Alternatively, use separate GET and POST registrations if your n8n version supports them without a path collision.

One thing that has not come up yet, and it lines up with the symptom exactly: the Meta test button and curl are manual calls, so they work regardless of the app’s state. Real events do not.

Meta’s Instagram Platform webhooks page puts it plainly: “Apps must be set to Live in the App Dashboard to receive webhook notifications.” With the app still in Development, verification passes, the subscription is stored, subscribed_apps looks correct, and no real DM is ever delivered. Nothing reaches your logs because nothing was sent.

Worth checking in this order, since each of these produces the same silence:

  1. App Dashboard, top bar: Development or Live.
  2. instagram_business_manage_messages granted, plus Advanced Access where it applies.
  3. The “Allow access to messages” toggle Deepankar pointed at, which lives in the Instagram
    app rather than the dashboard and resets on reauthorisation.

From our side, on publishing rather than messaging, we hit the same shape of problem: what Meta reports as state is not always the state. We had containers come back as FINISHED that were not actually ready to publish. So when the dashboard shows a subscription as active and nothing arrives, “active” is worth about as much as our FINISHED was.

Hi @Gio_Saliba ,

This usually happens because of a native Instagram app privacy setting, not an issue in n8n or Cloudflare.

Meta silently drops live DM webhooks if message access isn’t explicitly granted on the mobile app. Check the following:

  1. Allow Message Access in the Instagram App:
    Open the target business Instagram account on your phone:
    Settings and privacy > Messages and story replies > Connected tools > Enable Allow access to messages.
    (If this is turned off, Meta test events work, but real DMs will never be dispatched).
  2. Scope for Tester Account:
    Make sure the tester account has authorized the instagram_manage_messages permission when logging into your app.
  3. Handling GET & POST on a single Webhook:
    In n8n, set your Webhook node HTTP Method to ANY (or GET, POST depending on your n8n version). You can then branch with an If node checking {{ $json.query[‘hub.mode’] }} to return the verification challenge for GET requests and process message payloads for POST requests.

Try enabling the “Allow access to messages” toggle first, as that is almost always the missing link when test pings work but live DMs don’t.

Thanks!

I hit the exact same issue — webhook fully verified, curl and Meta’s own Test button trigger it fine (200 responses in logs, correct signature secret, correct subscribed_apps), but real DMs from actual users never arrive. Still unresolved on my end too, but here’s what I’ve ruled out so far, might save you some time:

Double-check the Instagram Webhooks subscription toggle specifically for the business account you’re testing with (not just the test/dev account) — found mine was OFF for the production account even though the test account had it on, which silently drops real messages while test button calls still work.

Confirm both sender AND recipient are added as Instagram Testers if you’re still in development mode — real DMs get silently dropped if either side isn’t a confirmed tester, even if the webhook itself is correctly subscribed.

If both of those check out, this might require either Meta support directly or passing App Review (I’m currently going the App Review route as a workaround).

Curious if you’ve found anything since posting — this seems like a common gap in Meta’s docs where “verified” doesn’t mean “will actually deliver.”

Four different root causes proposed and none confirmed usually means the boundary hasn’t been isolated yet, and a second person now seeing identical symptoms makes that more likely rather than less.

curl and Meta’s Test button are synthetic calls. They prove your tunnel, your webhook URL and your n8n node all work. They prove nothing about whether Meta ever emitted a real event. Those are two separate failures with identical symptoms, and right now you are both repeatedly testing the half that already works.

Split them. Point the same subscription at a bare request logger, anything that records raw inbound POSTs, or read the cloudflared access log directly. Then send yourself a real DM and look at whether ANY request arrives at the edge.

If nothing arrives, Meta never sent it. The cause is upstream (app mode, permissions, or the account-level message-access gate) and every further n8n-side change is wasted effort.

If something arrives but the workflow does not fire, it is on your side, and now you have the raw payload and the signature headers to diagnose against instead of guessing.

That is one test that eliminates half the search space rather than four more theories. Worth doing before changing anything else.