How Remote Logos Load into Invoice PDFs
In this article
In many web apps, a logo that looks fine in the editor can go missing from the downloaded PDF. The cause is usually browser security rules, not the logo itself. Invoice Generator avoids the problem with a small server-side image proxy. Here's what it does and when it's used.
Why a Logo from Another Website Is a Problem
Your PDF isn't created on our servers. The app draws the invoice in a hidden frame in your browser, turns it into an image, and saves that as a PDF. Browsers restrict that kind of drawing: if an image comes from another website that hasn't explicitly allowed it, the browser blocks the page from reading its pixels. A logo linked directly from another website, such as your own site or an image host, would often be missing from the PDF or stop the PDF from being created.
The Proxy Serves the Logo from Our Own Address
To avoid that, the PDF step rewrites the logo's address just before drawing. If the logo is a normal web link (http or https) to another website, the app replaces it with a link to its own image proxy, passing the original address along. Because the image now comes from the same site as the app, the browser lets the PDF step use it.
Logos that don't need this are left alone:
- Embedded image data, which is how uploaded logos and logos saved to your business profile are stored, is already part of the page.
- Images on our own site are already on the same site.
- Images held in the browser's memory come from the page itself.
In practice, the proxy mostly matters when a logo URL was typed into an invoice and the invoice hasn't yet been saved to an account, because saving to an account converts a remote logo into embedded image data.
What the Proxy Checks
The proxy doesn't simply forward anything it's given. For each request it:
- Checks the address is a valid http or https URL, and rejects anything else.
- Downloads the image from the original website.
- Checks the response really is an image, and refuses it otherwise, so a web page or file can't be passed off as a logo.
- Enforces a 2MB limit, first using the size the website reports and then again on the actual download, so a website that misreports the size can't get round it.
If any check fails, the proxy returns an error instead of an image. In that case, the fix is to upload the logo file directly, as described below.
Caching and Limits
A successful response tells the browser it may keep the image for 24 hours, so downloading several PDFs in a row doesn't fetch the same logo each time. The proxy has its own rate limit of 500 requests per 15 minutes per IP address, separate from the main app's limit, so a lot of PDF generation can't use up the limit you need for everything else.
The Most Reliable Option
The proxy handles remote logos, but the most reliable choice is still to upload your logo file directly, or save it in your business profile. Either way it's stored as embedded image data that goes with the invoice, so it doesn't depend on another website being online, and it appears the same in the editor, in the PDF, and on every share link. Keep the file small and clear, well under the 2MB limit, so PDFs stay quick to create and send.
Related Articles
How an Invoice Is Stored: One Row per Line Item, Plus a Full Copy
A saved invoice is stored as one database row per line item, linked by a shared group ID, with a full copy of the invoice on every row. Saving an edit replaces all of those rows in one transaction.
Why Sign-In Attempts Are Rate Limited
Sign-in, sign-up, two-factor checks, and verification resends share a budget of 10 attempts per hour per IP address, which is much stricter than the limit on ordinary app requests. Here's why the numbers differ.
How Sign-Up and Email Verification Actually Work
Creating an account sets up a personal workspace in the same database transaction, the verification link lasts 24 hours, and clicking an expired one quietly sends you a fresh link instead of leaving you stuck.
How Your Logo Gets Stored When You Upload It
A logo pasted in as a remote URL gets fetched server-side, checked against a 2MB cap and a real image content type, and converted into a self-contained data URL before it's saved.
Why You Get Logged Out After an Hour
Every session token expires in exactly one hour, and there's no refresh mechanism behind the scenes extending it quietly — plus the one deliberate exception carved out for two-factor logins.