- The server never sends the pack. It sends a URL and a SHA-1; each client downloads the zip itself, so the link must be a direct download.
- Set
resource-pack,resource-pack-sha1, and optionallyrequire-resource-packandresource-pack-promptinserver.properties. The limit is 250 MiB. - Rebuilt the zip? The hash changed. Recompute the SHA-1 every time you re-upload.
- Geyser does not convert Java packs. Bedrock players need a separate
.mcpackin Geyser'spacksfolder.
When a Minecraft server resource pack is not working, the server itself is almost never the problem, because the server never touches the file. It hands each player a URL and a SHA-1 hash from server.properties, and the player's game downloads the zip on its own. So "failed to download" means the client could not fetch a valid zip from your link, and "not loading" usually means it fetched one but the hash did not match, the pack was built for the wrong version, or the player has server packs disabled on their end.
This guide runs through the config keys, the hosting rules that trip most people, the exact fixes for each error, the difference between the client's Prompt and Enabled settings, and what Bedrock players through Geyser actually receive. Do the checks in order; the first three catch most cases.
What happens when a player joins
- The server sends the pack URL, the SHA-1 and the prompt text during login, straight from
server.properties. - The client checks its own setting. In the Edit Server screen, "Server Resource Packs" is Prompt by default; Enabled skips the question, Disabled refuses the pack.
- The client downloads the URL. It expects a zip file directly. An HTML page, a "click here to download" landing page, or a virus-scan interstitial all fail.
- The client compares the download's SHA-1 to the one you sent. A mismatch means the pack is rejected, or it is re-downloaded on every join because the cache key never matches.
- The client applies the pack. If
require-resource-pack=trueand the player declined, the server disconnects them.
The server.properties keys
These five keys, documented on the server.properties page, are the whole server-side story:
| Key | Default | What it does |
|---|---|---|
resource-pack | blank | The direct download URL of the zip. Maximum pack size is 250 MiB. |
resource-pack-sha1 | blank | Lowercase hex SHA-1 of the zip. Optional, but the wiki says "it is recommended to specify this," and without it the client cannot verify or cache properly. |
resource-pack-id | blank | An optional UUID that identifies this pack on the client side, so it is not confused with another server's pack. |
require-resource-pack | false | When true, players who decline the pack are disconnected. |
resource-pack-prompt | blank | Custom text shown in the prompt when require-resource-pack is on. Takes JSON text component syntax. |
A working example:
resource-pack=https://github.com/yourname/server-pack/releases/download/v12/pack.zip
resource-pack-sha1=2fd4e1c67a2d28fced849ee1bb76e7391b93eb12
resource-pack-id=6e1a2b4c-0d3f-4a5b-9c8d-7e6f5a4b3c2d
require-resource-pack=true
resource-pack-prompt={"text":"This server uses custom items and a 9 MB pack. Accept to see them.","color":"yellow"}
Get the hash from the file you actually uploaded: sha1sum pack.zip on Linux, shasum pack.zip on macOS, certutil -hashfile pack.zip SHA1 on Windows. Paste it in lowercase with no spaces. Restart the server; a reload does not re-read these keys reliably.
Hosting the zip: what "direct download" means
The URL has to return the raw zip bytes with nothing in front of it. That rules out most file-sharing pages. What works:
Upload the zip as a release asset. The link at github.com/you/repo/releases/download/<tag>/pack.zip is a direct download, versioned by tag, and free. This is the easiest option for a small team, and old versions stay available if you need to roll back.
Nginx, Caddy, Cloudflare R2, Backblaze B2 with a public bucket. Full control, and you can set the Content-Type to application/zip. Best once the pack is large or updated often.
Works only if the shared link ends in ?dl=1 instead of ?dl=0. The default link opens a preview page, which is the number one cause of "failed to download."
Avoid it. Files over a certain size get a virus-scan interstitial page instead of the file, and the link format changes. If a "resource pack link generator" site is selling you a Drive workaround, host it somewhere direct instead.
Failed to download, not loading: the fixes
| What the player sees | Likely cause | Fix |
|---|---|---|
| "Failed to download resource pack" instantly | The URL returns a web page, a redirect chain, or a 404 | Test the link in a private window; it must start a download. Fix the link, then restart the server. |
| Download runs to the end, then fails | The zip is over 250 MiB, or the hash does not match | Shrink the pack (below) and recompute resource-pack-sha1 from the uploaded file. |
| Pack re-downloads on every join | resource-pack-sha1 is blank or wrong, so the cache never matches | Set the correct lowercase SHA-1. Rebuilding the zip changes the hash even when the contents did not, because zip metadata differs. |
| Downloads fine, textures unchanged | Wrong pack_format in pack.mcmeta for the player's version, or the zip has an extra folder level | Open the zip: pack.mcmeta and assets/ must be at the root, not inside pack/. Check the pack_format table on the wiki for each version you support. |
| Some players get the prompt, others nothing | Those players set "Server Resource Packs" to Disabled, or a client mod overrides it | Tell them to edit the server entry and set it to Prompt or Enabled. If the pack is required, the server disconnects them with your prompt text, which is your chance to explain. |
| Works on Java, Bedrock players see vanilla | Geyser does not send Java packs to Bedrock | Ship a Bedrock pack through Geyser's packs folder (below). |
| Worked yesterday, broken today, nothing changed | The host of the file changed the link, expired it, or added an interstitial | Move to GitHub Releases or your own storage, where links do not change under you. |
Prompt versus Enabled, and when to require the pack
The confusion here is that "prompt" exists on both sides. On the client, the Edit Server screen's "Server Resource Packs" setting has three values: Prompt asks the player once per server, Enabled downloads without asking, Disabled never downloads. On the server, require-resource-pack decides what happens when a player says no. Mojang's bug tracker notes that before 1.20.3 a client on Prompt or Disabled behaved the same against a required pack; on current versions Disabled players are simply disconnected by a required pack.
- Optional pack (require false): the right default for cosmetic packs. Players who decline still play, and nobody bounces off your server because of a 30 MB download on hotel Wi-Fi.
- Required pack (require true): only when gameplay depends on it, such as custom items with model data, custom fonts for menus, or a game mode that is unplayable with vanilla textures. Write a
resource-pack-promptthat says what the pack is, how big it is, and why. Players are far more likely to accept a 9 MB pack explained in one sentence than an unexplained one. - Never require a pack purely for a logo on the loading screen. That is the fastest way to lose the first-join test in our get players guide.
Geyser and Bedrock players
Bedrock players who join through Geyser do not receive your Java pack. Geyser's resource pack page is explicit that it "does not convert resource packs from the Java Edition format into the Bedrock edition format." What you can do:
- Build or convert a Bedrock pack (
.mcpackor.zip). Geyser's page points to tools such as Rainbow and Thunder that make converting content simpler; expect to hand-fix models and fonts. - Drop it in Geyser's packs folder:
plugins/Geyser-Spigot/packs/on a plugin install,plugins/Geyser-Velocity/packs/on a proxy,config/Geyser-Fabric/packs/on Fabric. Restart, or reload Geyser. - Every Bedrock player then receives every pack in that folder on connect. There is no per-player prompt to design; keep the folder to what is needed.
Bedrock is a big slice of the audience for any crossplay server: on our list, Java servers that also answer a Bedrock ping have a median of 26 players online against 6 for Java-only servers. Many of them are on phones, which is the reason for the next section. Setup for the rest of the crossplay stack is in the crossplay guide.
Keep the pack small
The hard limit is 250 MiB, raised from 100 MiB in 1.18, but the practical limit is a phone on mobile data deciding whether to wait. Aim for under 20 MB unless the pack is the whole point of the server.
- Include only what you changed. A pack that copies every vanilla texture is huge and does nothing. Delete files you did not edit.
- Downscale. 16x textures are vanilla; 32x quadruples size for a marginal look. Sound files are usually the biggest offenders: use OGG at a modest bitrate and cut silence.
- Compress the zip properly. Deflate, normal compression. Store-only zips are common when people drag files in a hurry.
- Split cosmetic from required. Ship the small required pack through
server.propertiesand offer an optional high-resolution pack as a download link in Discord. - Version it. A new release tag per change (
v12,v13) keeps old links alive and makes "which pack do you have" a one-line question.
Once the pack loads cleanly for a fresh account on a slow connection, mention it on your listing description: custom items and models are a real reason to pick a server, and screenshots of them count toward the three photos in your listing strength. Claim your listing from its server page to edit those fields, and if you are launching a pack-driven server, a coming-soon listing can collect "Notify me" sign-ups while you finish it.
Quick questions
Where is the server resource pack location on the player's PC?
Downloaded server packs are cached under the game directory in downloads/ (inside .minecraft on a default install), named by hash. Deleting that folder forces a fresh download, which is a useful test when you suspect a stale cache.
Can I send more than one resource pack?
server.properties holds one. Since 1.20.3 the protocol allows servers to push several packs, and plugins use that, but the built-in setting is still a single URL. If you need layering, merge the packs into one zip; it is simpler for players anyway.
Do I need the SHA-1 if the pack is optional?
You should set it either way. Without a hash the client cannot tell whether its cached copy is current, so it re-downloads more often, and you lose the integrity check that catches a corrupted upload.
Why does the pack work for me but not for my friends?
You have it cached, or you are testing from the same machine that hosts it. Have a friend test from a fresh account on a different network, and try the link in a private browser window yourself. Different result usually means the link is not truly direct.
