TechEarl

How to Set or Stop an Animated GIF's Loop From the Command Line

Control how many times an animated GIF loops from the command line with gifsicle: play once, repeat a fixed number of times, or loop forever, plus the off-by-one count that trips everyone up and the inverse loop numbering in ffmpeg.

Ishan Karunaratne⏱️ 8 min readUpdated
Share thisCopied
Set or stop an animated GIF's loop count from the command line with gifsicle: play once, loop N times, or loop forever, and handle ffmpeg's inverse loop numbering.

To make an existing animated GIF loop a set number of times (or stop looping entirely) from the command line, use gifsicle and its --loopcount option:

bash
# Loop forever (the usual web default)
gifsicle --loopcount=forever in.gif -o out.gif
# Play through once and stop, no looping
gifsicle --no-loopcount in.gif -o once.gif
# Play once, then repeat 3 more times (4 plays total)
gifsicle --loopcount=3 in.gif -o loop3.gif

That is the whole job for most people. The rest of this page is the detail that actually trips people up: what the count number really means (it is not "how many times it plays"), the one value that does the opposite of what you expect (--loopcount=0 does not stop looping, it loops forever), verifying the result, and the separate, inverted way ffmpeg numbers loops when you are creating the GIF in the first place.

A GIF stores its loop behaviour in a small block called the Netscape Application Extension. It is the original 1990s convention every browser still honours: no extension means play once, an extension with a count of 0 means loop forever, and a non-zero count means loop that many times. gifsicle and ffmpeg are both just writing that one block. You do not need to re-encode the frames to change it, which is why these commands are instant.

Install gifsicle

bash
# macOS
brew install gifsicle
# Debian / Ubuntu
sudo apt install gifsicle
# Fedora
sudo dnf install gifsicle

gifsicle is a tiny, single-purpose tool from Eddie Kohler. It edits GIFs in place without the heavyweight dependency of ImageMagick, and it is the right tool for anything to do with loop state, frame timing, or optimizing an animated GIF.

The three loop modes

You wantOptionWhat it writes
Loop forever--loopcount=forever (or --loopcount=0)Netscape extension, count 0
Play once and stop--no-loopcountNo loop extension at all
Loop a fixed number of times--loopcount=NNetscape extension, count N
bash
gifsicle --loopcount=forever spinner.gif -o spinner-forever.gif
gifsicle --no-loopcount banner.gif -o banner-once.gif
gifsicle --loopcount=5 wave.gif -o wave-5.gif

The trap here is --loopcount=0. It reads like "zero loops, so play once," but the gifsicle manual is explicit that --loopcount=0 is equivalent to --loopcount=forever, not to --no-loopcount. A count of 0 in the Netscape block is the format's signal for infinite looping. To actually stop a GIF looping you want --no-loopcount, which strips the loop extension entirely. That is also gifsicle's default when you do not pass any loop option at all:

bash
gifsicle --no-loopcount in.gif -o once.gif

So if you run gifsicle for some other reason (resizing, optimizing) and forget to carry the loop setting through, you can silently turn a forever-looping GIF into a play-once one. Pass --loopcount=forever explicitly when you want the loop preserved.

The off-by-one that catches everyone

Here is the part the man page states plainly and almost everyone misreads. With --loopcount=N, N is the number of repeats after the first play, not the total number of plays. The animation runs once on its own, then loops N more times.

So --loopcount=3 gives you four plays in total: the initial run plus three loops. If you want a GIF to play exactly three times, you set the count to one less than that:

bash
# Plays a total of 3 times: once, then 2 repeats
gifsicle --loopcount=2 in.gif -o play-three-times.gif

This is not a gifsicle quirk; it is how the Netscape loop count is defined at the format level. Every tool that writes that block inherits the same "count of repeats after the first" meaning, which is exactly why the next section gets confusing.

Verify what you actually wrote

Do not trust your viewer; trust the file. gifsicle --info (or gifsicle -I) dumps the GIF's metadata, including the loop block:

bash
gifsicle --info out.gif

A forever-looping GIF shows a line like loop forever. A fixed-count GIF shows the count (loop count 3). A play-once GIF shows no loop line at all, because there is no extension to report. If you are doing a lot of these, grep for it:

bash
gifsicle --info out.gif | grep -i loop

For a fuller look at frame count, per-frame delays, and dimensions, see inspecting an animated GIF from the command line.

Setting the loop when you create the GIF with ffmpeg

If you are generating the GIF from a video rather than editing an existing one, ffmpeg's gif muxer has its own -loop option, and its numbering is the confusing inverse of gifsicle's. Memorise this table, because guessing it wrong is the single most common ffmpeg GIF complaint:

You wantffmpeg flag
Loop forever-loop 0 (this is the default)
Play once, no loop-loop -1
Loop N times-loop N
bash
# Loop forever (ffmpeg's default anyway)
ffmpeg -i in.mp4 -loop 0 out.gif
# Play once and stop
ffmpeg -i in.mp4 -loop -1 out.gif
# Loop 3 times
ffmpeg -i in.mp4 -loop 3 out.gif

Read that against the gifsicle table and the inversion is in the stop value, not the forever value. Both tools agree that 0 means loop forever (in gifsicle --loopcount=0 equals --loopcount=forever; in ffmpeg -loop 0 is the infinite default). They diverge on how you switch looping off: gifsicle uses --no-loopcount (a named flag, because --loopcount=0 is already taken by "forever"), while ffmpeg overloads the same -loop option with a negative value, -loop -1. Same underlying Netscape block, two tools that reached for different idioms to express "play once." The -loop flag also has to come before the output filename in the ffmpeg command, or it is silently ignored.

ffmpeg's positive -loop N carries the same off-by-one as gifsicle: N is repeats after the first play, so -loop 3 plays four times total. For the full high-quality video-to-GIF pipeline (the palettegen/paletteuse two-pass that ffmpeg needs to produce a clean GIF), see the ffmpeg command cheat sheet.

A practical note: if you already have the GIF and only need to change its loop behaviour, reach for gifsicle, not ffmpeg. Rewriting the loop block with --loopcount leaves the frames untouched and is instant; running it back through ffmpeg re-encodes every frame and degrades quality unless you redo the palette work.

FAQ

See also

Sources

Authoritative references this article was fact-checked against.

TagsgifsicleGIFffmpeganimated gifloop countCLIimage processing

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts