Skip to main content
RapidDev - Software Development Agency
stripe-guide

How to download invoices from Stripe

Download Stripe invoices from the Dashboard by going to Billing → Invoices, clicking an invoice, and clicking the PDF download button. For bulk or automated downloads, use the Stripe API to retrieve the invoice_pdf URL on each invoice object. You can also build a script to download all invoices for a customer or date range programmatically using Node.js.

What you'll learn

  • How to download individual invoices from the Stripe Dashboard
  • How to get invoice PDF URLs via the Stripe API
  • How to build a bulk invoice download script
  • How to generate invoice PDFs for customers programmatically
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner5 min read15 minutesStripe API v2024-12+, Node.js 18+March 2026RapidDev Engineering Team
TL;DR

Download Stripe invoices from the Dashboard by going to Billing → Invoices, clicking an invoice, and clicking the PDF download button. For bulk or automated downloads, use the Stripe API to retrieve the invoice_pdf URL on each invoice object. You can also build a script to download all invoices for a customer or date range programmatically using Node.js.

How to Access and Download Stripe Invoices

Stripe automatically generates invoices for subscription payments and one-time invoice charges. Each invoice has a hosted URL (viewable in browser) and a PDF URL (downloadable). You can access these through the Dashboard for one-off downloads, or use the API to automate bulk downloads for accounting, tax filing, or customer self-service portals.

Prerequisites

  • A Stripe account with at least one finalized invoice
  • Node.js 18+ for API-based downloads
  • The Stripe npm package installed

Step-by-step guide

1

Download from the Stripe Dashboard

Go to Stripe Dashboard → Billing → Invoices. Find the invoice you want and click on it. In the invoice detail view, click the download icon or 'Download PDF' button in the top-right area. You can also click 'View invoice' to see the hosted version in your browser.

Expected result: A PDF file is downloaded to your computer containing the full invoice details.

2

Get the invoice PDF URL via API

Each Stripe invoice object has an invoice_pdf field containing a direct URL to the PDF. Retrieve the invoice and access this URL to download programmatically.

typescript
1const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
2
3const invoice = await stripe.invoices.retrieve('in_abc123');
4
5console.log('PDF URL:', invoice.invoice_pdf);
6console.log('Hosted URL:', invoice.hosted_invoice_url);
7// PDF URL is a direct download link — valid without authentication

Expected result: You have the direct PDF download URL and the hosted browser-viewable URL for the invoice.

3

List all invoices for a customer

Use the API to retrieve all invoices for a specific customer. Filter by status and date range to find exactly what you need.

typescript
1const invoices = await stripe.invoices.list({
2 customer: 'cus_abc123',
3 status: 'paid',
4 limit: 100,
5});
6
7invoices.data.forEach(inv => {
8 console.log(`${inv.number} | ${inv.amount_paid / 100} ${inv.currency.toUpperCase()} | ${inv.invoice_pdf}`);
9});

Expected result: A list of all paid invoices for the customer with their PDF download URLs.

4

Build a bulk download script

Download all invoices for a customer (or all customers) as PDF files to a local directory. This is useful for year-end accounting or tax preparation.

typescript
1const fs = require('fs');
2const https = require('https');
3const path = require('path');
4
5async function downloadInvoicePDF(url, filename) {
6 return new Promise((resolve, reject) => {
7 const file = fs.createWriteStream(filename);
8 https.get(url, (response) => {
9 response.pipe(file);
10 file.on('finish', () => { file.close(); resolve(); });
11 }).on('error', reject);
12 });
13}
14
15async function downloadAllInvoices(customerId, outputDir) {
16 fs.mkdirSync(outputDir, { recursive: true });
17
18 let hasMore = true;
19 let startingAfter = undefined;
20
21 while (hasMore) {
22 const params = { customer: customerId, status: 'paid', limit: 100 };
23 if (startingAfter) params.starting_after = startingAfter;
24
25 const invoices = await stripe.invoices.list(params);
26
27 for (const inv of invoices.data) {
28 if (inv.invoice_pdf) {
29 const filename = path.join(outputDir, `${inv.number || inv.id}.pdf`);
30 await downloadInvoicePDF(inv.invoice_pdf, filename);
31 console.log(`Downloaded: ${filename}`);
32 }
33 }
34
35 hasMore = invoices.has_more;
36 if (invoices.data.length > 0) {
37 startingAfter = invoices.data[invoices.data.length - 1].id;
38 }
39 }
40}

Expected result: All paid invoices for the customer are downloaded as PDF files to the specified directory.

Complete working example

download-invoices.js
1require('dotenv').config();
2const fs = require('fs');
3const https = require('https');
4const path = require('path');
5const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
6
7function downloadFile(url, filepath) {
8 return new Promise((resolve, reject) => {
9 const file = fs.createWriteStream(filepath);
10 https.get(url, (res) => {
11 if (res.statusCode === 302 || res.statusCode === 301) {
12 // Follow redirect
13 https.get(res.headers.location, (redirectRes) => {
14 redirectRes.pipe(file);
15 file.on('finish', () => { file.close(resolve); });
16 }).on('error', reject);
17 } else {
18 res.pipe(file);
19 file.on('finish', () => { file.close(resolve); });
20 }
21 }).on('error', reject);
22 });
23}
24
25async function downloadCustomerInvoices(customerId, outputDir = './invoices') {
26 fs.mkdirSync(outputDir, { recursive: true });
27
28 let downloaded = 0;
29 let hasMore = true;
30 let startingAfter;
31
32 while (hasMore) {
33 const params = { customer: customerId, status: 'paid', limit: 100 };
34 if (startingAfter) params.starting_after = startingAfter;
35
36 const invoices = await stripe.invoices.list(params);
37
38 for (const inv of invoices.data) {
39 if (!inv.invoice_pdf) continue;
40 const name = `${inv.number || inv.id}.pdf`;
41 const filepath = path.join(outputDir, name);
42 await downloadFile(inv.invoice_pdf, filepath);
43 downloaded++;
44 console.log(`[${downloaded}] ${name}`);
45 }
46
47 hasMore = invoices.has_more;
48 if (invoices.data.length) {
49 startingAfter = invoices.data[invoices.data.length - 1].id;
50 }
51 }
52
53 console.log(`\nDone. Downloaded ${downloaded} invoices to ${outputDir}`);
54}
55
56// Usage: pass customer ID as argument
57const customerId = process.argv[2];
58if (!customerId) {
59 console.error('Usage: node download-invoices.js cus_xxx');
60 process.exit(1);
61}
62
63downloadCustomerInvoices(customerId).catch(console.error);

Common mistakes when downloading invoices from Stripe

Why it's a problem: Trying to download invoice PDFs for draft invoices

How to avoid: Only finalized invoices (status: 'paid', 'open', or 'void') have PDF URLs. Draft invoices don't have invoice_pdf set.

Why it's a problem: Storing invoice PDF URLs permanently

How to avoid: Invoice PDF URLs are temporary. Always retrieve a fresh URL from the API when you need to download. Don't cache URLs for long-term use.

Why it's a problem: Not handling pagination when listing invoices

How to avoid: The API returns a maximum of 100 invoices per request. Use has_more and starting_after to paginate through all results.

Why it's a problem: Not following redirects when downloading PDFs

How to avoid: Stripe PDF URLs may redirect. Your download function should follow 301/302 redirects to reach the actual PDF file.

Best practices

  • Use the Stripe Dashboard for quick one-off invoice downloads
  • Use the API and invoice_pdf URL for automated or bulk downloads
  • Always paginate when listing invoices — don't assume all results fit in one request
  • Handle HTTP redirects in your download function
  • Create a customer self-service portal using hosted_invoice_url for browser-viewable invoices
  • Filter by status and date range to download only the invoices you need
  • Store downloaded PDFs with the invoice number as filename for easy identification

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

Write a Node.js script that downloads all paid invoices for a Stripe customer as PDF files. Use the Stripe API to list invoices with pagination, get the invoice_pdf URL from each, and download them to a local directory. Handle redirects and use the invoice number as the filename.

Stripe Prompt

Build a Stripe invoice bulk download tool in Node.js. List all paid invoices for a customer with pagination, download each PDF via the invoice_pdf URL, handle HTTP redirects, and save files with invoice numbers as filenames.

Frequently asked questions

Where do I find invoices in the Stripe Dashboard?

Go to Billing → Invoices. You can filter by status (paid, open, draft, void) and search by customer name or invoice number.

Can customers download their own invoices?

Yes. Share the hosted_invoice_url with customers — it opens the invoice in a browser where they can view and download it. You can also build a customer portal using these URLs.

Are invoice PDF URLs permanent?

No. Invoice PDF URLs are temporary. Always retrieve a fresh URL from the API when you need to download. Don't store or cache URLs for long-term use.

Can I download invoices for all customers at once?

Yes. Use stripe.invoices.list() without a customer filter and paginate through all results. This works for year-end bulk downloads or accounting exports.

Do draft invoices have PDF URLs?

No. Only finalized invoices have invoice_pdf URLs. You must finalize a draft invoice (stripe.invoices.finalizeInvoice) before a PDF is generated.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.