Skip to main content
Glama
marcusquinn

Amazon Order History CSV Download MCP

by marcusquinn

get_amazon_order_details

Retrieve comprehensive Amazon order details including items, pricing, shipping, and payment information by providing the order ID and region.

Instructions

Get comprehensive details for a specific Amazon order by order ID. Returns full order data including: items (ASIN, name, price, quantity, seller, condition), financial breakdown (subtotal, shipping, tax, VAT, promotions, total), shipping address, payment methods, and optionally shipment tracking and transaction history.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
order_idYesAmazon order ID in format XXX-XXXXXXX-XXXXXXX (e.g., 123-4567890-1234567)
regionYesAmazon region code where the order was placed
include_shipmentsNoExtract shipment info from order detail page (default: true)
fetch_tracking_numbersNoExtract actual carrier tracking number (e.g., AZ218181365JE) by visiting the 'Track package' page. Adds ~2s per shipment.
include_transactionsNoInclude payment transaction details (default: false)

Implementation Reference

  • Main handler case for 'get_amazon_order_details' tool. Validates region and order_id, calls fetchOrders with orderId to enable single-order mode (includeItems: true, includeShipments: true by default), processes result[0] as the order, and returns structured JSON with order summary, items, shipments, transactions, and any errors.
    case "get_amazon_order_details": { const regionParam = args?.region as string | undefined; const regionError = validateRegion(regionParam, args); if (regionError) return regionError; const region = regionParam!; const currentPage = await getPage(); const orderId = args?.order_id as string; const includeShipments = args?.include_shipments as boolean | undefined; const fetchTrackingNumbers = args?.fetch_tracking_numbers as | boolean | undefined; const includeTransactions = args?.include_transactions as | boolean | undefined; // Use the same fetchOrders logic that works for get_amazon_orders const result = await fetchOrders(currentPage, amazonPlugin, { region, orderId, // This triggers single-order mode includeItems: true, includeShipments: includeShipments ?? true, fetchTrackingNumbers: fetchTrackingNumbers ?? false, includeTransactions: includeTransactions ?? false, }); const order = result.orders[0]; return { content: [ { type: "text", text: JSON.stringify( { status: result.errors.length > 0 ? "error" : "success", params: { orderId, region, includeShipments, fetchTrackingNumbers, includeTransactions, }, order: order ? { id: order.id, date: order.date?.toISOString(), total: order.total, shipping: order.shipping, tax: order.tax, recipient: order.recipient, payments: order.payments, itemCount: order.items?.length || 0, shipmentCount: order.shipments?.length || 0, } : null, items: result.items.map((i) => ({ name: i.name, asin: i.asin, quantity: i.quantity, unitPrice: i.unitPrice, condition: i.condition, seller: i.seller?.name, subscriptionFrequency: i.subscriptionFrequency, })), shipments: result.shipments.map((s) => ({ shipmentId: s.shipmentId, status: s.status, delivered: s.delivered, trackingId: s.trackingId, carrier: s.carrier, trackingLink: s.trackingLink, itemCount: s.items?.length || 0, })), transactions: result.transactions.map((t) => ({ date: t.date.toISOString(), amount: t.amount, vendor: t.vendor, cardInfo: t.cardInfo, })), errors: result.errors, }, null, 2, ), }, ], }; }
  • Tool schema definition: requires order_id and region, optional include_shipments (default true), fetch_tracking_numbers, include_transactions. Describes comprehensive order details extraction.
    { name: "get_amazon_order_details", description: "Get comprehensive details for a specific Amazon order by order ID. Returns full order data including: items (ASIN, name, price, quantity, seller, condition), financial breakdown (subtotal, shipping, tax, VAT, promotions, total), shipping address, payment methods, and optionally shipment tracking and transaction history.", inputSchema: { type: "object", properties: { order_id: { type: "string", description: "Amazon order ID in format XXX-XXXXXXX-XXXXXXX (e.g., 123-4567890-1234567)", }, region: { type: "string", description: "Amazon region code where the order was placed", enum: getRegionCodes(), }, include_shipments: { type: "boolean", description: "Extract shipment info from order detail page (default: true)", default: true, }, fetch_tracking_numbers: { type: "boolean", description: "Extract actual carrier tracking number (e.g., AZ218181365JE) by visiting the 'Track package' page. Adds ~2s per shipment.", default: false, }, include_transactions: { type: "boolean", description: "Include payment transaction details (default: false)", default: false, }, }, required: ["order_id", "region"], }, },
  • src/index.ts:638-640 (registration)
    Registration of all tools (including get_amazon_order_details via the tools array) by handling ListToolsRequestSchema and returning the tools list.
    server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools }; });
  • Core helper function fetchOrders handles single-order mode when orderId provided. Navigates to invoice URL first for fast item extraction, falls back to detail page, optionally extracts shipments and transactions from detail page. Called by the handler with orderId flag.
    if (orderId) { console.error( `[fetch-orders] Fetching single order: ${orderId} (region: ${region})`, ); onProgress?.(`Fetching order ${orderId}...`, 0, 1); // Create header for this order const header: OrderHeader = { id: orderId, orderId, date: null, total: { amount: 0, currency, currencySymbol, formatted: "" }, detailUrl: `https://www.${domain}/gp/your-account/order-details?orderID=${orderId}`, platform: "amazon", region, }; const enrichedOrder: EnrichedOrder = { ...header }; // Go to invoice page and extract items directly (inline, with timeouts) const invoiceUrl = `https://www.${domain}/gp/css/summary/print.html?orderID=${orderId}`; console.error(`[fetch-orders] Navigating to invoice: ${invoiceUrl}`); await page.goto(invoiceUrl, { waitUntil: "domcontentloaded", timeout: 15000, }); const currentUrl = page.url(); console.error(`[fetch-orders] Current URL: ${currentUrl}`); await page .waitForSelector('[data-component="purchasedItems"], table, .a-box', { timeout: 3000, }) .catch(() => {}); // Check for error banners (e.g., "We're unable to load your order details") const errorBanner = await page .locator( '[data-component="errorbanner"], .a-alert-error, .a-alert-info', ) .first(); const errorBannerCount = await errorBanner.count().catch(() => 0); if (errorBannerCount > 0) { const errorText = await errorBanner .textContent({ timeout: 500 }) .catch(() => ""); if ( errorText?.includes("unable to load") || errorText?.includes("problem loading") ) { console.error( `[fetch-orders] Error detected: ${errorText.slice(0, 200)}`, ); result.errors.push( `Order page error: ${errorText.slice(0, 200).trim()}`, ); } } // Try to extract items - first try data-component, then fall back to extractFromInvoice const itemContainers = await page .locator('[data-component="purchasedItems"]') .all(); console.error( `[fetch-orders] Found ${itemContainers.length} purchasedItems containers on invoice page`, ); // Invoice pages often don't have data-component, try the full invoice extractor if (itemContainers.length === 0) { console.error( `[fetch-orders] No data-component items found, using extractFromInvoice`, ); const invoiceData = await extractFromInvoice(page, header); // Copy over invoice data (amounts, recipient, payments) regardless of items console.error( `[fetch-orders] Invoice data: subtotal=${invoiceData.subtotal?.formatted}, total=${invoiceData.total?.formatted}, vat=${invoiceData.vat?.formatted}, shipping=${invoiceData.shipping?.formatted}`, ); if (invoiceData.subtotal) enrichedOrder.subtotal = invoiceData.subtotal; if (invoiceData.total) enrichedOrder.grandTotal = invoiceData.total; if (invoiceData.shipping) enrichedOrder.shipping = invoiceData.shipping; if (invoiceData.tax) enrichedOrder.tax = invoiceData.tax; if (invoiceData.vat) enrichedOrder.vat = invoiceData.vat; if (invoiceData.gift) enrichedOrder.promotion = invoiceData.gift; if (invoiceData.recipientName) { enrichedOrder.recipient = invoiceData.recipientName; if (invoiceData.shippingAddress) { // Prepend recipient name as line1 if address doesn't start with it const addressWithName = [ invoiceData.recipientName, ...invoiceData.shippingAddress, ]; enrichedOrder.shippingAddress = parseInvoiceAddressLines(addressWithName); } } if (invoiceData.payments && invoiceData.payments.length > 0) { enrichedOrder.payments = invoiceData.payments; // Also set paymentMethod from first payment const firstPayment = invoiceData.payments[0]; enrichedOrder.paymentMethod = { type: firstPayment.method, lastFour: firstPayment.lastFour, }; } // Convert invoice items to full Item type if found if (invoiceData.items && invoiceData.items.length > 0) { // Create enriched header with all order data for items const enrichedHeader: OrderHeader = { ...header, recipient: typeof enrichedOrder.recipient === "string" ? enrichedOrder.recipient : undefined, subtotal: enrichedOrder.subtotal, shipping: enrichedOrder.shipping, tax: enrichedOrder.tax, vat: enrichedOrder.vat, promotion: enrichedOrder.promotion, grandTotal: enrichedOrder.grandTotal, shippingAddress: enrichedOrder.shippingAddress, paymentMethod: enrichedOrder.paymentMethod, }; const items = invoiceData.items.map((ii) => ({ id: ii.asin || ii.name.slice(0, 50), asin: ii.asin, name: ii.name, quantity: ii.quantity, unitPrice: ii.unitPrice, totalPrice: { ...ii.unitPrice, amount: ii.unitPrice.amount * ii.quantity, formatted: `${currencySymbol}${(ii.unitPrice.amount * ii.quantity).toFixed(2)}`, }, url: ii.asin ? `https://www.${domain}/dp/${ii.asin}` : "", orderHeader: enrichedHeader, condition: ii.condition, seller: ii.seller ? { name: ii.seller } : undefined, subscriptionFrequency: ii.subscriptionFrequency, platformData: { source: "invoice" }, })); console.error( `[fetch-orders] extractFromInvoice found ${items.length} items`, ); enrichedOrder.items = items; result.items = items; } } // Only use inline extraction if we found data-component containers (detail page) // Otherwise extractFromInvoice already handled it above if (itemContainers.length > 0) { // Create enriched header with all order data for items const enrichedHeader: OrderHeader = { ...header, recipient: typeof enrichedOrder.recipient === "string" ? enrichedOrder.recipient : undefined, subtotal: enrichedOrder.subtotal, shipping: enrichedOrder.shipping, tax: enrichedOrder.tax, vat: enrichedOrder.vat, promotion: enrichedOrder.promotion, grandTotal: enrichedOrder.grandTotal, shippingAddress: enrichedOrder.shippingAddress, paymentMethod: enrichedOrder.paymentMethod, }; const extractedItems: Item[] = []; for (const container of itemContainers) { try { // Title + ASIN const titleLink = container .locator('[data-component="itemTitle"] a') .first(); const titleCount = await titleLink.count().catch(() => 0); if (titleCount === 0) continue; const name = await titleLink .textContent({ timeout: 500 }) .catch(() => ""); if (!name?.trim()) continue; const href = await titleLink .getAttribute("href", { timeout: 500 }) .catch(() => ""); const asinMatch = href?.match(/\/dp\/([A-Z0-9]+)/i); const asin = asinMatch ? asinMatch[1] : undefined; // Price const priceEl = container .locator('[data-component="unitPrice"] .a-offscreen') .first(); const priceText = await priceEl .textContent({ timeout: 500 }) .catch(() => ""); const priceMatch = priceText?.match(/[£$€]?([\d,.]+)/); const priceAmount = priceMatch ? parseFloat(priceMatch[1].replace(",", "")) : 0; // Quantity (check badge first, then quantity component) let quantity = 1; const qtyBadge = container .locator(".od-item-view-qty span") .first(); const qtyBadgeCount = await qtyBadge.count().catch(() => 0); if (qtyBadgeCount > 0) { const qtyText = await qtyBadge .textContent({ timeout: 500 }) .catch(() => ""); const qtyMatch = qtyText?.match(/(\d+)/); if (qtyMatch) quantity = parseInt(qtyMatch[1], 10); } // Seller let seller: string | undefined; const sellerEl = container .locator('[data-component="orderedMerchant"]') .first(); const sellerCount = await sellerEl.count().catch(() => 0); if (sellerCount > 0) { const sellerText = await sellerEl .textContent({ timeout: 500 }) .catch(() => ""); const sellerMatch = sellerText?.match(/Sold by:\s*(.+)/i); if (sellerMatch) seller = sellerMatch[1].trim(); } // Condition let condition: string | undefined; const condEl = container .locator('[data-component="itemCondition"]') .first(); const condCount = await condEl.count().catch(() => 0); if (condCount > 0) { const condText = await condEl .textContent({ timeout: 500 }) .catch(() => ""); const condMatch = condText?.match(/Condition:\s*(.+)/i); if (condMatch) condition = condMatch[1].trim(); } // Subscription frequency let subscriptionFrequency: string | undefined; const freqEl = container .locator('[data-component="deliveryFrequency"]') .first(); const freqCount = await freqEl.count().catch(() => 0); if (freqCount > 0) { const freqText = await freqEl .textContent({ timeout: 500 }) .catch(() => ""); const freqMatch = freqText?.match(/Auto-delivered:\s*(.+)/i); if (freqMatch) subscriptionFrequency = freqMatch[1].trim(); } extractedItems.push({ id: asin || name.trim().slice(0, 50), asin, name: name.trim(), quantity, unitPrice: { amount: priceAmount, currency, currencySymbol, formatted: `${currencySymbol}${priceAmount.toFixed(2)}`, }, totalPrice: { amount: priceAmount * quantity, currency, currencySymbol, formatted: `${currencySymbol}${(priceAmount * quantity).toFixed(2)}`, }, url: asin ? `https://www.${domain}/dp/${asin}` : "", orderHeader: enrichedHeader, condition, seller: seller ? { name: seller } : undefined, subscriptionFrequency, platformData: { source: "invoice" }, }); } catch { continue; } } console.error( `[fetch-orders] Extracted ${extractedItems.length} items from data-component`, ); // Store items if (extractedItems.length > 0) { enrichedOrder.items = extractedItems; result.items = extractedItems; } } // If no items found from invoice, try the detail page if (result.items.length === 0 && result.errors.length === 0) { console.error( `[fetch-orders] No items from invoice, trying detail page extraction`, ); await page.goto(header.detailUrl, { waitUntil: "domcontentloaded", timeout: 15000, }); await page .waitForSelector('[data-component="purchasedItems"], .a-box', { timeout: 2000, }) .catch(() => {}); // Check for error banners on detail page const detailErrorBanner = await page .locator( '[data-component="errorbanner"], .a-alert-error, .a-alert-info', ) .first(); const detailErrorCount = await detailErrorBanner.count().catch(() => 0); if (detailErrorCount > 0) { const errorText = await detailErrorBanner .textContent({ timeout: 500 }) .catch(() => ""); if ( errorText?.includes("unable to load") || errorText?.includes("problem loading") ) { console.error( `[fetch-orders] Detail page error: ${errorText.slice(0, 200)}`, ); result.errors.push( `Order detail error: ${errorText.slice(0, 200).trim()}`, ); } } if (result.errors.length === 0) { const items = await plugin.extractItems(page, header).catch(() => []); if (items.length > 0) { console.error( `[fetch-orders] Found ${items.length} items from detail page`, ); enrichedOrder.items = items; result.items = items; } } } // Get shipments from detail page if requested if (includeShipments) { console.error(`[fetch-orders] Fetching shipments from detail page`); // Only navigate if not already there if (!page.url().includes("order-details")) { await page.goto(header.detailUrl, { waitUntil: "domcontentloaded", timeout: 15000, }); await page .waitForSelector('[data-component="shipments"], .a-box', { timeout: 2000, }) .catch(() => {}); } const shipments = await plugin .extractShipments(page, header, fetchTrackingNumbers) .catch(() => []); enrichedOrder.shipments = shipments; result.shipments = shipments; console.error(`[fetch-orders] Found ${shipments.length} shipments`); } // Get transactions if requested if (includeTransactions) { const transactions = await plugin .extractTransactions(page, header) .catch(() => []); result.transactions = transactions; console.error( `[fetch-orders] Found ${transactions.length} transactions`, ); } result.orders = [enrichedOrder]; result.totalFound = 1; return result; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/marcusquinn/amazon-order-history-csv-download-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server