How countdown timers in email actually work
By Danish Mohammed, founder. , updated 13 min read
Almost everything written about countdown timers in email describes what they do for a campaign. Almost none of it says what they are, and every question people actually ask turns out to be a question about the mechanism.
The short version: a countdown timer in an email is a picture at a web address, and the picture does not exist until somebody asks for it.
What a countdown timer in an email actually is
An email cannot run code. Every large client removes <script> tags before a message is displayed, which rules out the setInterval loop that drives a countdown on a web page. Frames, embedded objects and form controls go the same way. Microsoft’s own documentation of the Word rendering engine that classic Outlook uses lists script, iframe and object among the elements it does not support at all.
What survives is the image tag. So the countdown has to be an image, and an image that changes has to be drawn at the moment it is requested.
That is the whole trick. Your snippet contains an <img> whose src points at a rendering service. When a mail client displays the message, it makes an ordinary HTTP GET to that address. The service looks up the deadline the template was published with, subtracts the current time from it, draws the frames, and streams back an animated GIF.
The image is built per request, so two people opening the same message an hour apart get two different pictures from one URL. Nothing in the email changed. The email was only ever a pointer.
This is also why a downloaded GIF cannot do the job. A GIF is a fixed list of frames with fixed delays, and nothing inside it knows what time it is. A generator that hands you a file to save and upload builds that file once, at the moment you press the button. Every recipient of every send afterwards sees a countdown to a deadline that was already stale when the file was attached.
One more thing follows from the image being drawn on demand. Anything else that belongs in the picture can be drawn at the same time. A subscriber’s name and a live clock can be rendered into one GIF by one pass of the same engine. That is why the countdown and the personalized image are one product here rather than two subscriptions. Where no motion is wanted, the same engine returns a PNG instead.
The frames themselves are finite too. At one frame per second, a minute of motion is sixty pictures, and every vendor in this category caps the count to keep the file sendable. Customer.io states its cap outright: “The countdown timer GIF cannot contain more than 60 frames.” The default here is 30 frames, configurable between 20 and 60, and each template sets whether the last frame holds on screen or the animation loops back to a number that is already stale. The caps across the category are collected in why your timer stops after a minute.
The three moments that matter
A countdown has three candidate starting points, and confusing them is the source of most of the trouble in this subject.
Send. Your platform hands the message to the mail servers. Nothing is rendered. No image has been requested yet, and the deadline in the URL is just text in a template.
The delivery fetch. Some clients ask for the images when the message arrives, before any human has seen it. Apple Mail’s Protect Mail Activity is the large one. Apple’s own description of the feature says it “downloads remote content in the background by default”. The render that results reflects the moment of delivery.
The open. Other clients ask for the image when the reader opens the message. Gmail works this way. Google states the mechanism in one sentence: “When your users open email messages, Gmail uses Google’s secure proxy servers to serve images that might be included in these messages.”
A timer is accurate for whichever of those moments produced the fetch that the reader is looking at. That sounds like a technicality until you write a welcome email that says “48 hours from when you open this” and send it to a list that is 40 percent Apple Mail.
Apple documents the prefetch and Google documents the proxy. Neither publishes how long its cache holds a copy. The two to three days is from FreshInbox's 2021 testing of Mail Privacy Protection, not from Apple.
Caching is the fourth complication, sitting on top of those three. Once a client or proxy has a copy, a second view may not produce a second request. FreshInbox’s 2021 testing reports that Apple holds images for two to three days and that Apple Mail “does not respect the ‘Cache-Control’ headers that specify when a cached image should expire”, where Gmail honours them. Google publishes no lifetime for its own proxy cache, so any figure you have been quoted for Gmail came from a vendor’s observation rather than from Google.
There is one lever a vendor has over that, and it is the response headers. A live timer here is served with Cache-Control: public, max-age=0, s-maxage=30, no-transform, must-revalidate and an ETag over the exact bytes. Gmail honours those headers. Apple Mail, by FreshInbox’s account, does not. So the header work buys accuracy in one large client and nothing at all in the other, and no amount of cache busting changes that. Cache busting has a cost of its own, too: a URL that is unique per view cannot be cached anywhere, which multiplies the renders your allowance is spending.
Longer write-ups of this section are on the blog: each provider’s cache on its own, Apple’s shared image cache, and the Outlook report of timers resuming from a cached frame.
What each client does
This is the summary. There is a page per client with the sources and the version detail behind it, at countdown timers client by client.
| Client | When it fetches | Animates | What the reader sees |
|---|---|---|---|
| Gmail, web and app | At open, through Google’s proxy | Yes | The first open is accurate. A later open can be served from the copy Google already holds |
| Apple Mail with Protect Mail Activity | At delivery | Yes | The numbers as of delivery. Testing reports the copy is held two to three days |
| Outlook 2007, 2010, 2013 on Windows | At open | No | Frame one only. Microsoft documents that “only a static representation of the GIF image shows” |
| Outlook 365 classic on Windows | At open | Only when animations are enabled | Frame one when the Windows setting is off |
| New Outlook for Windows, Outlook on the web | At open | Yes | A May 2025 Microsoft Q&A thread reports it resuming from a cached frame with the wrong numbers |
| Outlook on iOS and Android | At open | Yes | A live countdown |
Two entries in that table decide most design choices. Frame one has to be a correct, finished picture, because for a large share of corporate readers it is the whole timer. And a fixed deadline is the only model that is immune to when the fetch happened, because the target is the same instant no matter who asks or when.
None of the rows above has been watched in a real inbox by me. They are read off vendor documentation and public reports, which is why the client pages say “documented” rather than “tested”, and they will keep saying it until that changes.
The four timer types, and which campaign each fits
| Timer | Where the deadline comes from | Fits | Watch out for |
|---|---|---|---|
| Fixed date | One instant, the same for everybody | Flash sales, Black Friday, a webinar start, a price rise | Nothing much. This is the model caching cannot hurt |
| Per-recipient deadline | A value that belongs to one person, such as a cart expiry | Cart abandonment, price-drop alerts, voucher expiry | The value has to be inside the signed URL, so the URL is minted per recipient rather than merged in the template |
| Evergreen from first open | The reader’s own first fetch of the image | Welcome sequences, onboarding, an always-on offer | Apple Mail’s first fetch is delivery. One campaign address is also one shared clock, so a start per person needs an address per person |
| Evergreen from send | The send timestamp your platform passes | Long flows where Apple Mail and Gmail need to agree | Your platform has to be able to pass a send time |
Two more models exist and are used less often. A count-up timer runs forward from a past moment, for anniversaries and milestones. A recurring timer resets on a schedule, for a weekly order cutoff, and it is only honest when the offer genuinely resets. All six are set out in timer types. Two have a guide of their own: evergreen timers that start when each person opens, and timers that reset on a schedule, which includes where the FTC drew the line on a reset.
If you take one thing from this table, take the first row. When a deadline is real and shared, use a fixed date. Every other model buys per-person urgency at the cost of depending on when a fetch happened.
Cart abandonment is the case that most wants a per-recipient deadline and most needs the caveat. The cart expiry is real, it belongs to one person, and it arrived on the trigger event. Set it as a per-recipient deadline rather than an evergreen clock. The number on the image is then the number in your database, so an Apple Mail reader whose image was fetched at delivery still sees a true statement about their own cart.
Evergreen from first open is at its best where the deadline is something you invented anyway. A welcome offer that lasts 48 hours from the reader’s first look is a reasonable thing to build. A 48-hour window that quietly started at delivery for part of the list is a worse thing, and it is what happens if you do not plan for it.
What the snippet contains, and why
The code for a campaign timer is one image inside one link. The full table-wrapped version, with the fallback for classic Outlook, is in the HTML for an email countdown timer.
<a href="https://example.com/sale" target="_blank" rel="noopener">
<img src="https://img.emailtimer.app/i/k7mQ2pXd.gif?w=w_8ha3fq&v=3&sig=YOUR_SIGNATURE"
alt="Flash sale ends at midnight UTC on Friday"
width="600" height="200" border="0"
style="display:block; width:100%; max-width:600px; height:auto; border:0;" />
</a>
Every part of that is there for a reason.
src is a signed URL. The path names the template, and the query carries the workspace, the version and, for per-recipient timers, an opaque recipient token. sig is an HMAC over the canonicalised query, so nobody can edit a parameter and get a render out of it. The same canonical string is also what the rendered image is cached under.
That signature has a consequence people meet the hard way. A merge tag cannot go inside the image URL. Your platform substitutes the value after the signature was taken, verification fails, and the service answers with a fallback picture at HTTP 200 rather than an error. The campaign looks healthy in every report and looks wrong in every inbox. Merge tags belong in the href and the alt, which are not signed.
For a per-recipient timer the shape changes in exactly one place. The src becomes a merge tag pointing at a contact field that holds a signed URL you minted per recipient, usually through the API. Everything else in the snippet stays as it is. That is the only way the recipient token can be inside the signature and inside the template at once.
alt is copy rather than a label. Many corporate clients hide remote images until the reader asks for them, and for those people the alt text is the entire message. Write the deadline into it.
width and height are HTML attributes as well as CSS, because classic Outlook renders through Word and Word ignores most CSS. border="0" stops older clients drawing a blue frame around a linked image. display:block removes the gap some clients leave under an inline image.
The link wrapper carries target and rel for the clients that open in a browser tab. And the whole thing is one image, so a personalized layer and a countdown can arrive in the same picture rather than as two assets to approve.
What can go wrong, and where to look
Four symptoms cover nearly everything.
The timer is stuck. The reader is looking at a cached copy, or the frames have run out. The decision tree is at why your email timer is stuck.
The timer shows the wrong time. Usually a time zone that was assumed rather than stated, or a fetch that happened earlier than you think. That one is at why your timer shows the wrong time.
The timer does not move. Almost always Outlook on Windows with animations disabled. Microsoft is direct about it: “If only the first frame of the animation appears, you have animations, or animated GIFs, disabled.” The setting is a Windows accessibility toggle on current builds, which means you cannot reach it and the recipient does not know it exists. The full version is on countdown timers in Outlook.
The timer is a broken image. Check that the URL survived your platform’s link rewriting, that the signature is intact, and that no merge tag was spliced into the query string. Some platforms also carry a setting that hides or rewrites image URLs, which breaks a signed one.
The timer stopped after a minute. The GIF ran out of frames. Show a larger smallest unit: a seconds column on a three-day countdown is stale a second after it is drawn, where a minutes column stays right for most of the time it is on screen.
Where the snippet goes in your platform
Every sending platform takes this in one of two ways. Either it has a block for raw HTML, which is where the snippet goes, or it has an image block with a URL field, which takes the image URL on its own. Klaviyo and Brevo call theirs an HTML block. Mailchimp and SendGrid call theirs a Code block. HubSpot puts it behind the Advanced menu of a rich text module. The ones that give you neither take the image URL into an ordinary picture block, and you add the link and the alt text in the block’s settings.
The exact merge-tag syntax differs per platform, and the wrong syntax fails silently rather than loudly. The platform setup guides carry the tags each one uses.
A timer in an email signature is a different job, because every message you send requests it, replies and forwards included, and every one of those fetches counts. That one is covered in putting a countdown timer in your email signature.
Making one
The free countdown timer generator produces a working timer and hands over the snippet before anything asks for an email address. There is no watermark, and the deadline can be up to 90 days out. A timer from the free generator works for 500 opens without an account, and for 1,000 once you sign in and claim it. After that, the image shows a note that its free opens are used up.
What it cannot do is change its mind. A generator timer has no owner, so the deadline and the design are fixed once published, and it is swept thirty days after its deadline. Variants of the same tool are pre-set for Klaviyo, Mailchimp, Gmail and Outlook.
What it costs
The free plan is 5,000 image opens a month with no watermark inside that allowance, and an open means a fetch of the image rather than a human reading anything. Starter is $19 or Rs 1,599 for 250,000 opens, Growth is $49 or Rs 3,999 for 1,000,000, and Agency is $149 for 5,000,000. Every timing model is on every plan, and so are personalized images, because they come out of the same render engine. What Growth adds is the API and the recipient sets that mint one signed address per person, which is what a deadline that genuinely differs per reader needs.
Past 110 percent of an allowance new renders carry a small corner watermark and keep rendering, because a delivered email cannot be recalled and a broken image is never the right answer. The full table, in dollars and rupees, is on pricing.
Questions and answers
Do countdown timers work in every email client?
They display everywhere, because they are images. Whether they animate depends on the client, and classic Outlook for Windows shows only the first frame when animations are disabled. That is why frame one carries the real time remaining.
Why does my timer show a different time to different people?
Because the picture is drawn when each client asks for it, and the clients ask at different moments. Apple Mail asks at delivery, Gmail asks at the open, and a cached copy can be shown again later without a new request.
Can I put a countdown timer in an email without code?
Yes. Take the image URL instead of the HTML snippet and paste it into an ordinary image block. Set the width to match, and add the link and the alt text in the block’s own settings.
Is a countdown timer bad for deliverability?
A heavy image can be, because file size and the ratio of images to text are things filters look at. A 600 by 200 timer at a sensible frame count is a small file. The GIF checker reads the numbers out of any file you have.
What happens after the deadline passes?
The image keeps answering and shows the design at zero with an expired line under it. It never becomes a broken image, which matters because a campaign can be forwarded weeks later.
Do I need an account?
Not to make one. The generator publishes a timer and hands over the code with nothing asked for, and that timer works for 500 opens. Sign in and claim it, and the same timer works for 1,000. An account is what makes a deadline movable, an open countable, and a timer per recipient possible.
Sources
- Mail Privacy Protection (Apple Legal)
- Set up an image URL proxy allowlist (Google Workspace Admin Help)
- The animated graphic in my e-mail message doesn't work (Microsoft Support)
- Word 2007 HTML and CSS Rendering Capabilities in Outlook 2007 (Part 1 of 2)
- A Technical Take on iOS15 Mail Privacy Protection (FreshInbox, 29 July 2021)
- Liquid recipes (Customer.io Docs)
Related
Put a countdown in the campaign you are writing now
The free plan covers 5,000 opens a month with no card. Starter is $19 a month for 250,000.