smallcord

Make any file fit Discord's upload limit

Drop a file, pick your Discord tier, and see instantly whether it will send — all in your browser.

New here? Jump straight to a common job — the right tool opens with your tier and sensible options pre-filled:

File size checker

Your Discord tier Which one?
Drop a file above or click to choose one. Nothing is sent anywhere — your file is read locally to measure its size.
No file handy? Check by size instead

Already know the size? Enter it to see which Discord tier it fits as-is — no file needed, nothing is sent.

Everything runs in your browser — your files never leave your device.

How it works

1

Pick your tier

Choose 10 MB (free), 50 MB (Nitro Basic), or 500 MB (Nitro) to match the account you'll upload from.

2

Drop your file

Your browser reads the file locally and shows its exact size against your limit. No upload happens.

3

Get it under the cap

If it's over, smallcord shows how much it must shrink. The image, video, GIF and audio pages re-encode the file right in your browser — image and video take several files at once — and each also generates a one-line local ffmpeg command as a reliable fallback.

Which tool do I need?

The box above only measures: it reads your file locally, prints its exact size and tells you how far over your tier it is. The shrinking happens on one of four pages, and what each of those pages can actually do to a file is genuinely different — one of them re-encodes in every browser, three of them depend on what your browser can encode. This table is the honest map, so you can go straight to the right one.

What you have, where it goes, and what that page really does to it.
What you haveToolWhat actually happens there
Screen recording or game clip — OBS, ShadowPlay, Xbox Game Bar, an .mp4 or .mkv Video Computes the exact video bitrate that lands under your tier, then re-encodes the clip on your device if your browser exposes a WebCodecs H.264 or VP9 encoder — MP4 or WebM out, with a separate audio budget, optional trim and a queue for several clips. If that encoder is missing, you still get the settings plus a one-line local ffmpeg command.
Phone video — a .mov or .mp4 straight off an iPhone or Android Video Same page, same maths. This is the case where the planner most often has to say no: a few minutes of 4K at a phone's native bitrate does not fit 10 MB at any watchable quality, and the page tells you that plainly instead of handing back a bitrate that would produce a smeared mess.
Voice memo, recorded call, podcast cut — .m4a, .mp3, .wav, .ogg Audio Audio has two levers: bitrate and length. The page reads the clip's length locally, computes the highest bitrate whose re-encode still lands under your cap, and — where the browser has a WebCodecs Opus encoder — hands you the smaller file directly. Length is yours to pull: the optional Start / End trim boxes start empty and stay empty unless you fill them in, so nothing is shortened behind your back, and when even the 32 kbps floor won't fit, the page offers the span that does as a one-click prefill you confirm. Without that encoder, the same numbers as an ffmpeg command.
Meme GIF — a real animated .gif, usually a few hundred KB to a few dozen megabytes GIF Converts it to a silent MP4 or WebM, which Discord autoplays inline exactly like a GIF and which is typically 5–20× smaller, using WebCodecs where the browser has it. A keep-it-a-GIF fallback (scale down, drop frames, cut the palette) is offered too, and is labelled an estimate because it is.
Photo or screenshot — .png, .jpg, .webp, one file or forty Image The one page that needs nothing exotic: it re-encodes through a plain canvas, so it works in every current browser. In Auto (smallest) it steps quality down, then resolution, until the file fits; switch Output format to Lossless (PNG) for line art, pixel art or a transparent screenshot: it keeps every pixel and fits with two levers, colours and resolution — it spends a colour budget first, laddering an indexed PNG down 256 → 128 → 64 → 32 → 16 at full size before it will resize anything (photographs are refused that ladder and resized instead), and the PNG colours control lets you force Auto, 256, 64 or 16 yourself — and it says so, offering your original back, when the PNG still comes out bigger than the file you dropped in. Either way it shows the real before/after byte counts. Several images at once come back as a .zip.
A ZIP, an installer, a PDF, a save file — anything already compressed No tool, and we will not pretend otherwise. The checker above will tell you the exact number you are over by; from there the honest options are splitting the archive into parts or using a file host and pasting the link. Re-zipping a ZIP buys you nothing.

One rule spans all four: data that is already compressed well does not compress much further. A modern H.264 clip that was encoded at a sensible bitrate, a JPEG saved at quality 80, an MP3 at 128 kbps — squeezing those means throwing away picture or sound, not finding slack. smallcord's job is to tell you exactly how much you have to throw away, and to refuse the job when the answer is "all of it".

What actually fits

Where these numbers come from. Every figure in this section was produced by requiring smallcord's own planner modules in Node — assets/fit-math.js, assets/fit-audio.js, assets/fit-gif.js and assets/codec-budget.js, the exact files your browser runs on the tool pages — through tools/home-figures.cjs in the source tree. They are the planner's arithmetic, not a benchmark: no file was encoded to make this table, and nothing here is copied from anyone's marketing page. Where a figure needs an assumption the planner cannot supply — "how many kbps does watchable 1080p need?" — it is called a rule of thumb, in those words, and the assumption is stated.

Video: how long a clip fits

Fitting video is a bitrate problem. fit-math.js takes the byte budget, the clip length and an audio bitrate, and returns the video bitrate that should land under the cap. The table below feeds it a fixed 96 kbps audio track — enough for speech and game sound — and reads back the video bitrate at four lengths.

Video bitrate the planner allots, in kbps, with audio held at 96 kbps.
Tier30 s1 min2 min5 min
Free, 10 MB2,6191,263584178
Nitro Basic, 50 MB13,4686,6873,2971,263
Nitro, 500 MB135,52267,71433,81013,468

The arithmetic behind the 1,263 in that first row, in full: the free tier's 10 MB is binary megabytes, so 10,485,760 bytes. Times 8 gives 83,886,080 bits; divided by 1,000 that is 83,886.08 kbit of budget; spread over 60 seconds it is 1,398.1 kbps for everything in the file. Take away the 96 kbps of audio and 1,302.1 kbps is left for picture. Multiply by the planner's 0.97 safety margin — 3% held back for MP4/WebM container overhead the raw sum ignores — and you get 1,263 kbps. That is also why the free tier at one minute and Nitro Basic at five minutes land on exactly the same 1,263 kbps: five times the budget spread over five times the length is the same number twice.

Turning bitrate into "will it look acceptable" needs one assumption the module does not make, so here it is as a rule of thumb: decent 1080p30 H.264 wants roughly 2,500 kbps, and 720p30 roughly 1,200 kbps. Feed those back through the same planner and the free tier holds about 31 seconds of 1080p or 1 min 2 s of 720p; Nitro Basic holds 2 min 36 s of 1080p or 5 min 14 s of 720p; Nitro holds 26 min 8 s of 1080p or 52 min 26 s of 720p. Treat those as the shape of the problem, not a promise — a static talking head beats the rule of thumb easily, and confetti, rain or fast camera pans blow straight through it.

There is also a hard floor. fit-math.js refuses to plan below 100 kbps of video, because below that you get smeared soup rather than a watchable clip. On the free tier that floor is reached at 6 min 59 s with 96 kbps audio: past that length the planner returns an infeasible verdict with a suggestion (trim it, drop the resolution, or use a bigger tier) instead of a useless number. The in-browser encoder's own splitter, codec-budget.js, is stricter still: at the free tier it reserves 314,573 bytes — the same 3% — for container overhead before it hands anything to the encoder, and when a clip gets long enough it drops audio to the 32 kbps floor rather than starve the picture.

Audio: how long a voice memo fits

Audio size is bitrate × length, so there are two levers and only one is smallcord's to pull on its own. Bitrate is automatic: fit-audio.js divides the budget by the length and clamps the result between a 32 kbps floor (below which even Opus turns speech to artefacts) and a 320 kbps ceiling (the top standard MP3 rate — past it a re-encode is pointless). Length is the second lever, and it is your call: the in-browser compressor on /audio/ has optional Start / End boxes that stay empty unless you fill them in, and when a recording can't fit even at the 32 kbps floor it offers the span that does fit — floorFitPlan()'s maxFitSeconds, 42:22 for a 10 MB target — as a one-click prefill you still have to confirm. Nothing is ever shortened behind your back, and blank boxes compress the whole file.

Bitrate and codec the audio planner recommends for a clip of each length.
Tier5 min10 min30 min60 min
Free, 10 MB271 kbps MP3135 kbps MP345 kbps Opusno honest plan
Nitro Basic, 50 MB320 kbps MP3320 kbps MP3226 kbps MP3113 kbps MP3
Nitro, 500 MB320 kbps MP3320 kbps MP3320 kbps MP3320 kbps MP3

The codec column is not decoration: the module recommends Opus at or below 96 kbps, where it comfortably beats MP3, and MP3 above that, where the gap has closed and compatibility matters more. For the 10-minute free-tier row it also returns its own size estimate — 10,438,144 bytes, leaving 47,616 bytes of headroom under the cap. The "no honest plan" cell is the module talking, not us shrugging: an hour of audio in 10 MB works out below the 32 kbps floor, so it returns an infeasible verdict and suggests splitting the recording instead. The longest clip each tier can hold right at that floor is 42 min 22 s on free, 3 h 31 m on Nitro Basic and about 35 hours on Nitro.

GIFs: how many frames fit

GIF is a 1987 format that stores a palette-indexed bitmap per frame, so its size scales with pixels × frames and barely at all with how much the picture moves. fit-gif.js models that as roughly 0.4 bytes per pixel per frame after LZW at a reduced palette — the module's own documented heuristic, and honestly a rough one. Feeding it a 480×480 GIF at 15 fps, here is where staying a GIF runs out.

A 480×480, 15 fps animation: how much of it survives at full size as a real .gif.
TierFrames at full sizeThat isSame clip as silent MP4
Free, 10 MB113 frames7.5 sup to 13 min 25 s
Nitro Basic, 50 MB568 frames37.9 sup to 1 h 7 min
Nitro, 500 MB5,688 frames379.2 sup to 11 h 11 min

Push past those frame counts and the GIF path starts taking things away: at 150 frames (10 seconds) the free tier's plan is to scale the GIF to about 87% of its width and height, and at 300 frames (20 seconds) to about 61% — and below 20% linear scale the module gives up and says so. The MP4 column is the whole argument for the GIF page's default. That same 113-frame clip, planned as a silent MP4 against the same 10 MB, gets 10,801 kbps — an absurd amount of bitrate for 480×480 — and the free tier only runs out of MP4 budget at 13 min 25 s of animation. Discord animates the MP4 inline, so the visible result is a GIF that plays normally and is a fraction of the size.

One honest caveat on this table specifically: the MP4 numbers are pure bitrate arithmetic and dependable, but the frame counts come from that 0.4 bytes-per-pixel-per-frame heuristic, and real GIF sizes swing by 2–3× with content. Flat cartoon cels with big areas of one colour beat the estimate comfortably; grainy camera footage dithered into 256 colours misses it. The GIF page says the same thing next to its own plan.

What smallcord will and will not do

Where the numbers come from

All the arithmetic on this site lives in small, dependency-free modules that run identically in your browser and in Node, and each one is pinned by a golden-vector test in the repository. That is deliberate: a fit planner that quietly changes its answers is worse than no planner, so the numbers are tested before any encoder touches them.

The recurring 3% is worth explaining, because it is the difference between a plan that fits and one that overshoots by a hair. A file is not just its media bitrate: an MP4 or WebM also carries headers, an index of where every frame starts, per-frame timestamps and packet framing, and none of that appears in a bitrate × duration multiplication. Reserving 3% up front covers it with room to spare on typical clips, which is why smallcord would rather hand you a file comfortably under your limit than one that lands just over it and makes you do the whole thing twice.

Questions

Is it safe? Does my file get uploaded anywhere?

No file is uploaded. smallcord runs entirely in your browser, so the file you drop is read on your own device and never sent to a server — there is no backend that could receive it. You can verify this in your browser's Network tab: choosing a file triggers zero network requests.

Which Discord tier should I pick?

Match the tier to the account doing the upload. Free Discord accounts can attach files up to 10 MB; Nitro Basic raises that to 50 MB, and full Nitro to 500 MB. Server boosts can raise a server's ceiling, but the per-message limit is still set by your subscription — so choose based on your account, not the server.

What file types will it handle?

This page reads any file and tells you how far over your limit it is, then points you to the right tool. Images re-encode to WebP/JPEG in your browser, one at a time or as a batch, or to lossless PNG if you ask for that instead — that path writes a real indexed PNG, exactly lossless when the image already uses 256 colours or fewer, and a PNG colours control can force 256, 64 or 16; H.264 video, GIF and audio re-encode in your browser too with the browser's built-in WebCodecs — the video page outputs H.264/MP4, or VP9/WebM where your browser can encode it, lets you set the audio budget, and can queue several clips. Every page also generates a one-line local ffmpeg command as a reliable fallback. Already-compressed data like ZIPs or low-bitrate H.264 rarely shrinks much further — smallcord will say so plainly rather than pretend.

Do I need an account? Are you tracking me?

No account, no ad tracking. There's no sign-up or login and no advertising scripts. The only analytics is a self-hosted, cookieless GoatCounter that counts an anonymous pageview — no cookies, no profile, and it never sees your file. Your file itself is never stored or transmitted.

How long can a video be and still fit the free 10 MB limit?

That depends on resolution far more than most people expect. With audio held at 96 kbps, smallcord's planner gives a 60-second clip 1,263 kbps of video, a 2-minute clip 584 kbps and a 5-minute clip just 178 kbps. Using the common rule of thumb that watchable 1080p30 needs around 2,500 kbps, about 31 seconds of 1080p fits the free tier, or roughly a minute at 720p. Beyond 6 min 59 s the planner stops planning: less than 100 kbps would be left for the picture, and it returns an infeasible verdict rather than a bitrate that would produce smeared soup.

Why do I sometimes get an ffmpeg command instead of a finished file?

Because your browser could not do the encode itself. The video, GIF and audio pages use WebCodecs, the browser's own built-in encoder, and support genuinely varies — some builds ship no H.264 encoder, some no Opus encoder. smallcord checks that live rather than guessing from your user-agent, and when the check fails it falls back to the path that always works: the exact settings it computed, printed as a one-line local ffmpeg command. There is deliberately no bundled FFmpeg build to fall back on, because every obtainable WebAssembly FFmpeg core is GPL or outright non-redistributable, and this site vendors only MIT, Apache or BSD code.

Will my GIF still be a GIF?

By default, no — and that is the point. The GIF page's primary route converts the animation to a silent MP4 or WebM, which Discord autoplays inline exactly like a GIF while being typically 5–20× smaller. For a 480×480 animation at 15 fps, staying a real .gif means about 113 frames — 7.5 seconds — before the free tier's 10 MB is spent, while the same clip planned as an MP4 does not run out of budget until roughly 13 minutes. If you specifically need a .gif file, the page still offers that route: it scales the image down, drops frames and cuts the palette, and it labels the result an estimate because GIF sizes swing by 2–3× with content.

How accurate are these numbers?

The bitrate figures are exact arithmetic on your file's real size and duration, both read on your own device — they are not benchmarks and nothing was encoded to produce them. What they cannot promise is a byte-exact output, because a real encoder only hits a target average bitrate with some tolerance. Every planner therefore holds back 3% of the budget for container overhead, which is why a plan usually lands comfortably under the limit rather than a hair over it. The one figure that is genuinely rough is the keep-it-a-GIF estimate, which assumes about 0.4 bytes per pixel per frame after compression; flat cartoons beat that and grainy footage misses it.

Are you affiliated with Discord?

No. smallcord is independent and not affiliated with, endorsed by, or sponsored by Discord Inc. We name "Discord" only to describe what the tool does: help a file fit Discord's upload limits.