How to capture raw HTTP data when calling bot.send_invoice with Python Telegram Bot?

I’m working with a Telegram bot that sends payment invoices, but my payment provider says they’re getting malformed data in the provider_data field. They need me to share the complete HTTP request details to help debug this issue.

My current code:

import json
from telegram import Bot, Update, LabeledPrice
from telegram.ext import ContextTypes

PAY_TOKEN = '111111111111111'
INV_PAYLOAD = 'Payment-Debug'
PRODUCT_CATALOG = {"202410DEBUGITEM": ["DEBUG Item",
                                     "Testing payment integration functionality.",
                                     50,
                                     "https://example.com",
                                     "https://example.com/logo.png",
                                     "logo.png",
                                     ],
                  }

async def process_payment_request(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user_id, first_name, last_name, user_handle = (update.effective_user.id,
                                                   update.effective_user.first_name,
                                                   update.effective_user.last_name,
                                                   update.effective_user.username)
    
    item_key = str(context.user_data['selected_item'])
    product_title = f'{PRODUCT_CATALOG[item_key][0]}'
    product_desc = f'{PRODUCT_CATALOG[item_key][1]}'
    price_label = f'Purchase of {item_key.upper()}'
    price_value = int(PRODUCT_CATALOG[item_key][2])
    currency_type = 'USD'
    
    receipt_data = {
        "receipt": {
            "email": context.user_data['user_email'],
            "items": [{
                "description": price_label,
                "quantity": "1.00",
                "amount": {
                    "value": f'{price_value:.2f}',
                    "currency": currency_type,
                },
                "vat_code": 1,
            }],
        },
    }
    
    provider_json = json.dumps(receipt_data)
    
    await context.bot.send_invoice(
        user_id,
        product_title,
        product_desc,
        INV_PAYLOAD,
        PAY_TOKEN,
        currency_type,
        [LabeledPrice(price_label, price_value * 100)],
        provider_data=provider_json,
        reply_to_message_id=update.effective_message.id
    )

I tried using Python’s logging module with DEBUG level but it only shows the API parameters, not the actual HTTP request body that gets sent to Telegram’s servers.

import logging

logging.basicConfig(
    filename='debug_output.log',
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.DEBUG
)

This gives me logs like this but not the raw HTTP data:

2024-09-14 13:58:53,713 - telegram.ext.ExtBot - DEBUG - Calling Bot API endpoint `sendInvoice` with parameters...

I’m thinking about switching to the requests library instead. How can I see the exact HTTP request being made?

tbh just monkey patch the bot’s http client to log requests before sending. wrap the _request method and dump the payload to a file. way easier than wireshark or proxy stuff. intercept right before it hits telegram’s api and you’ll see the exact json in the provider_data field

You can intercept the raw HTTP traffic by configuring the underlying httpx client that python-telegram-bot uses. Just set up logging for httpx to see the complete request and response data.

import logging
import httpx

# Enable httpx debug logging
logging.getLogger("httpx").setLevel(logging.DEBUG)

This captures the actual HTTP payload without rewriting your existing bot code. The httpx logger shows you full request headers, body, and response details that Telegram gets.

Or you could set up a custom HTTPAdapter when you initialize your Bot to route requests through a debugging proxy like mitmproxy or Charles Proxy. This gives you more detailed inspection and lets you save the complete request/response cycle to share with your payment provider.

I had good luck combining urllib3 logging with a network capture tool. Since python-telegram-bot uses httpx (which runs on urllib3), you can get detailed request logs like this:

import urllib3
urllib3.disable_warnings()
logging.getLogger('urllib3.connectionpool').setLevel(logging.DEBUG)

But honestly, the most reliable approach is just using Wireshark or tcpdump to capture the actual network packets while your bot’s running. You’ll see the complete HTTP conversation - headers, body, everything exactly as it’s sent. Run your payment test somewhere isolated and filter for HTTPS traffic to api.telegram.org. If you need to decrypt the TLS traffic, configure your environment to log the TLS keys. This cuts out any middleware issues and shows your payment provider exactly what Telegram’s getting from your bot.