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
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
Pick your tier
Choose 10 MB (free), 50 MB (Nitro Basic), or 500 MB (Nitro) to match the account you'll upload from.
Drop your file
Your browser reads the file locally and shows its exact size against your limit. No upload happens.
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 | Tool | What 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.
| Tier | 30 s | 1 min | 2 min | 5 min |
|---|---|---|---|---|
| Free, 10 MB | 2,619 | 1,263 | 584 | 178 |
| Nitro Basic, 50 MB | 13,468 | 6,687 | 3,297 | 1,263 |
| Nitro, 500 MB | 135,522 | 67,714 | 33,810 | 13,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.
| Tier | 5 min | 10 min | 30 min | 60 min |
|---|---|---|---|---|
| Free, 10 MB | 271 kbps MP3 | 135 kbps MP3 | 45 kbps Opus | no honest plan |
| Nitro Basic, 50 MB | 320 kbps MP3 | 320 kbps MP3 | 226 kbps MP3 | 113 kbps MP3 |
| Nitro, 500 MB | 320 kbps MP3 | 320 kbps MP3 | 320 kbps MP3 | 320 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.
| Tier | Frames at full size | That is | Same clip as silent MP4 |
|---|---|---|---|
| Free, 10 MB | 113 frames | 7.5 s | up to 13 min 25 s |
| Nitro Basic, 50 MB | 568 frames | 37.9 s | up to 1 h 7 min |
| Nitro, 500 MB | 5,688 frames | 379.2 s | up 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
- It re-encodes images in any current browser. The image page uses a plain canvas to decode and re-encode to WebP or JPEG, or to lossless PNG when you pick that. No exotic API — if the page loads, it can shrink your picture. PNG output is not just whatever the canvas hands back: smallcord builds a colour palette and writes a real indexed (colour-type-3) PNG. That is exactly lossless when your image already uses 256 colours or fewer, which is what Auto waits for while a file still fits; when it does not fit, the colour budget ladders the palette down at full size rather than letting your line art be resized, and the result line names the palette it spent. The PNG colours control also lets you force 256, 64 or 16 colours, which is lossy in colour only — every pixel and every transparent pixel stays, at full resolution — and which turns smallcord's own 1344×768 social card from 194.0 KB of truecolour into 44.1 KB. That indexed pass also scores all five PNG filter types on every scanline and keeps whichever of the two encodings deflates smaller, so its output can never be larger than it was without the search. The ceiling is still real and the image page still publishes it: smallcord runs no zopfli and no second compression pass, so a file oxipng or pngquant has already been over can still come out bigger here — and when it does, PNG mode says so and gives you your original back rather than the bigger file.
- It re-encodes video, GIFs and audio when your browser can. Those three pages use WebCodecs, the browser's own built-in encoder, muxed with vendored MIT/BSD JavaScript (mp4-muxer, webm-muxer, mp4box.js — all pinned, with their licence text stored in the repo). Support is checked live, by asking the browser whether it can encode that configuration, never by guessing from a user-agent string.
- It tells you when it can't, and gives you the command instead. Some browsers ship no H.264 encoder, some no Opus encoder. When the check fails, the page says so plainly and falls back to the thing that always works: the computed settings as a one-line ffmpeg command you can copy and run locally.
- It will never run ffmpeg inside your browser. This is a licensing decision, recorded in the
repository as
DROP-SC3.md. The JavaScript wrapper around a WebAssembly FFmpeg is MIT, but the wasm core that does the actual encoding is not:@ffmpeg/core@0.12.10declares GPL-2.0-or-later and its embedded FFmpeg configure line reads--enable-gpl --enable-libx264 --enable-libx265; version 0.12.6 claims MIT in its package metadata while shipping the byte-identical GPL configure line; and 0.11.0 is built--enable-nonfreewith libfdk-aac, which makes it flatly non-redistributable. This portfolio vendors only MIT, Apache or BSD code, so the transcode path was dropped rather than shipped on a licence we cannot honour. There is no plan to revisit it. - It will not upload your file. Ever. There is no backend to upload to — smallcord is static HTML, CSS and JavaScript on a webserver, with every library stored as a local file rather than pulled from a CDN. You do not have to take that on faith: open your browser's Network tab, then drop a file. Choosing and processing a file produces zero network requests. Beyond the page's own files, the only request is a single cookieless GoatCounter pageview ping when the page loads, which happens before you have picked anything and carries no information about your file.
- It will not promise a byte-exact result. Every planner holds back 3% of the budget for container overhead and every real encoder hits a target average bitrate with some tolerance. Plans are conservative on purpose so a "this fits" verdict rarely comes back over the limit, but a plan is an estimate and the pages say so where they show one.
- It will not make already-compressed data smaller for free. Nothing here beats physics on a ZIP, an installer or a video that was already encoded efficiently. Where there is no honest win, the tool says there is no honest win.
- It will not ask you for anything. No account, no email, no sign-in, no cookie banner, no ads.
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.
assets/budget.js— the single source of truth for the three tier sizes, in binary megabytes: 10 MB is 10,485,760 bytes, not 10,000,000. Every page and every planner reads its limits from here, and a repository test fails the build if any page's prose quotes a limit that is not in that table — which is how a stale number from an older Discord policy gets caught instead of shipped.assets/fit-math.js— the video bitrate planner: a 0.97 safety margin, a 32 kbps audio floor and a 100 kbps minimum video bitrate below which it returns infeasible rather than a number.assets/codec-budget.js— what the in-browser video encoder actually plans with. It splits the budget between video and audio, prefers 128 kbps audio, and steps audio down to the 32 kbps floor only when the picture would otherwise fall under the watchable minimum.assets/fit-audio.js— the audio planner: same 3% headroom, a 32 kbps floor, a 320 kbps ceiling, and the Opus-below-96-kbps codec choice.assets/fit-gif.js— the GIF planner: the silent-MP4 route as the default, plus the keep-it-a-GIF model with its 10 fps frame-rate floor and 20% scale floor.
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.