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
Download from the Stripe Dashboard
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.
Get the invoice PDF URL via API
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.
1const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);23const invoice = await stripe.invoices.retrieve('in_abc123');45console.log('PDF URL:', invoice.invoice_pdf);6console.log('Hosted URL:', invoice.hosted_invoice_url);7// PDF URL is a direct download link — valid without authenticationExpected result: You have the direct PDF download URL and the hosted browser-viewable URL for the invoice.
List all invoices for a customer
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.
1const invoices = await stripe.invoices.list({2 customer: 'cus_abc123',3 status: 'paid',4 limit: 100,5});67invoices.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.
Build a bulk download script
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.
1const fs = require('fs');2const https = require('https');3const path = require('path');45async 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}1415async function downloadAllInvoices(customerId, outputDir) {16 fs.mkdirSync(outputDir, { recursive: true });1718 let hasMore = true;19 let startingAfter = undefined;2021 while (hasMore) {22 const params = { customer: customerId, status: 'paid', limit: 100 };23 if (startingAfter) params.starting_after = startingAfter;2425 const invoices = await stripe.invoices.list(params);2627 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 }3435 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
1require('dotenv').config();2const fs = require('fs');3const https = require('https');4const path = require('path');5const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);67function 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 redirect13 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}2425async function downloadCustomerInvoices(customerId, outputDir = './invoices') {26 fs.mkdirSync(outputDir, { recursive: true });2728 let downloaded = 0;29 let hasMore = true;30 let startingAfter;3132 while (hasMore) {33 const params = { customer: customerId, status: 'paid', limit: 100 };34 if (startingAfter) params.starting_after = startingAfter;3536 const invoices = await stripe.invoices.list(params);3738 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 }4647 hasMore = invoices.has_more;48 if (invoices.data.length) {49 startingAfter = invoices.data[invoices.data.length - 1].id;50 }51 }5253 console.log(`\nDone. Downloaded ${downloaded} invoices to ${outputDir}`);54}5556// Usage: pass customer ID as argument57const customerId = process.argv[2];58if (!customerId) {59 console.error('Usage: node download-invoices.js cus_xxx');60 process.exit(1);61}6263downloadCustomerInvoices(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.
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.
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.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation