RE:NODE

API загрузки PaperMC: скрипты для jar Paper, Velocity и Folia

Автор Команда RE:NODE
15 мин чтения


Если ваш скрипт до сих пор скачивает Paper с api.papermc.io/v2/..., он сломан: API v2 отключили 1 июля 2026 года, и теперь любой запрос к нему возвращает 410 Gone. Замена - Fill API по адресу https://fill.papermc.io/v3/, и переход несложный, если знать, как он устроен. Вы запрашиваете /v3/projects/paper/versions/<version>/builds?channel=STABLE, берёте первую сборку из списка, и JSON отдаёт готовую ссылку на скачивание на fill-data.papermc.io вместе с контрольной суммой sha256. Передавайте User-Agent, который называет ваш скрипт и содержит контакт, проверяйте контрольную сумму и закрепляйте ту сборку, которую вы проверили, вместо погони за самой свежей. Дальше в статье подробности: все нужные эндпоинты, что означают каналы, готовый скрипт обновления и ошибки, после которых на сервере остаётся недокачанный jar.

Что случилось с api.papermc.io/v2#

Годами ссылка на jar Paper выглядела одинаково, и тысячи скриптов, Dockerfile и инструкций по установке записали её прямо в код:

code
https://api.papermc.io/v2/projects/paper/versions/<ver>/builds/<build>/downloads/<file>.jar

Её собирали из трёх частей - версии Minecraft, номера сборки и имени файла, которое всегда было paper-<ver>-<build>.jar, - и если номер сборки был известен, файл можно было скачать, ни о чём не спрашивая API. Этого удобства больше нет. PaperMC заменила старый сервис Bibliothek новым, который называется Fill, а эндпоинты v2 закрыла. Сегодня и эндпоинты метаданных, и старые ссылки на скачивание отвечают так:

code
HTTP/1.1 410 Gonesunset: Wed, 1 Jul 2026 00:00:00 GMT{"ok":false,"error":"sunset","message":"This API version has been sunset and isno longer available. To continue using the service, please upgrade to a supportedAPI version."}

Ни перенаправления, ни переходного периода не осталось. Если стартовый скрипт сервера скачивает jar при каждом запуске или образ контейнера тянет Paper на этапе сборки, симптом такой: wget или обычный curl "успешно" скачивает файл и оставляет вам JSON на 176 байт под именем server.jar. Java отказывается его запускать с ошибкой Error: Invalid or corrupt jarfile server.jar, и люди начинают разбираться с версиями Java вместо того, чтобы посмотреть на URL. Если использовать curl -f (завершаться с ошибкой при ответах HTTP с кодом ошибки), проблема проявится как понятная ошибка на шаге загрузки. Именно с этого начинается скрипт ниже.

Заметьте также, что api.papermc.io/v3 не существует: новый API живёт на другом хосте, fill.papermc.io, а сами jar - на третьем, fill-data.papermc.io. Если на вашем файрволе или прокси есть список разрешённых адресов для исходящего трафика, изменились все три имени.

Эндпоинты Fill v3#

API v3 - небольшое REST-дерево той же формы, что и раньше (проекты, версии, сборки), и везде JSON. Вот запросы, которые действительно нужны скрипту:

ЭндпоинтЧто возвращает
/v3/projectsВсе проекты с их версиями
/v3/projects/paperОдин проект, версии сгруппированы по семействам
/v3/projects/paper/versions/26.3Статус поддержки, минимальная Java, id сборок
/v3/projects/paper/versions/26.3/buildsВсе сборки, новые первыми, полные данные
/v3/projects/paper/versions/26.3/builds?channel=STABLEТот же список, только один канал
/v3/projects/paper/versions/26.3/builds/189Одна сборка по номеру
/v3/projects/paper/versions/26.3/builds/latestНовейшая сборка любого канала

Все они относятся к https://fill.papermc.io. Идентификаторы проектов - paper, folia и velocity; закрытые прокси waterfall и travertine по-прежнему указаны ради своих старых сборок, но новых для них не выпускают.

Эндпоинт проекта группирует версии по семействам: сначала новейшее семейство, внутри семейства сначала новейшая версия:

json
{"project":{"id":"paper","name":"Paper"}, "versions":{"26.3":["26.3","26.3-rc-3"],             "26.2":["26.2","26.2-rc-2"],             "26.1":["26.1.2","26.1.1"],             "1.21":["1.21.11","1.21.11-rc3", "...", "1.21"]}}

Здесь два момента. Во-первых, в 2026 году нумерация версий самого Minecraft перешла на схему с годом, поэтому список идёт от 26.3 назад до 1.21.11 и дальше, а всё, что сортирует версии как строки, расставит их в неправильном порядке. Во-вторых, релиз-кандидаты и пре-релизы (26.3-rc-3, 1.21.11-pre5) лежат в одном списке с настоящими релизами. Скрипт, который берёт "первую версию из списка", однажды выберет релиз-кандидат. Если нужен новейший релиз автоматически, отфильтруйте идентификаторы, содержащие -, - хотя, как сказано ниже, выбирать версию Minecraft автоматически в любом случае плохая идея.

Эндпоинт версии люди упускают из виду, а для аккуратного скрипта он полезнее всего:

json
{"version":{"id":"1.21.4",            "support":{"status":"UNSUPPORTED","end":"2025-07-17"},            "java":{"version":{"minimum":21},                    "flags":{"recommended":["-XX:+UseG1GC", "..."]}}}, "builds":[232, 231, "..."]}

Поле support.status говорит, поддерживает ли PaperMC эту версию (SUPPORTED или UNSUPPORTED с датой окончания), а java.version.minimum - какая Java нужна для jar: 21 для линейки 1.21 и 25 для выпусков 26.x. Скрипт может отказаться ставить jar, который Java на этой машине не запустит, и это куда дружелюбнее, чем UnsupportedClassVersionError при старте. Рекомендуемые флаги - привычный набор для G1; что делает каждый из них, объясняет статья флаги JVM для Minecraft и версии Java.

Объект сборки содержит всё, что нужно, чтобы скачать и проверить jar:

json
{"id":189, "time":"2026-10-14T20:17:18Z", "channel":"STABLE", "commits":[{"sha":"a48059a2...","message":"Correctly serialise decorated pod ..."}], "downloads":{"server:default":{    "name":"paper-26.3-189.jar",    "checksums":{"sha256":"3a90c2ea79a81cd0ce641c9954c616828be6d32255385aef3b2022f80b91e8b5"},    "size":55150184,    "url":"https://fill-data.papermc.io/v1/objects/3a90c2ea.../paper-26.3-189.jar"}}}

Ключ загрузки - server:default для всех трёх проектов (в v2 было application), и так как в ключе есть двоеточие, в jq его нужно брать в кавычки: .downloads."server:default".url. Сам URL адресуется по содержимому - в пути лежит sha256 jar, - поэтому для данной сборки он никогда не меняется, и его можно безопасно кешировать. Не собирайте этот URL сами, берите его из API. Это главное отличие от v2, где составлять URL из версии и сборки было нормальным способом работы.

Ошибки приходят в виде JSON с кодом error и соответствующим статусом HTTP: несуществующая сборка даёт 404 с build_not_found, неизвестная версия - version_not_found. Для тех, кто предпочитает GraphQL, есть и такой эндпоинт, https://fill.papermc.io/graphql; в этой статье везде используется REST, потому что curl и jq есть на каждой машине с Linux.

Каналы: ALPHA, BETA и STABLE#

В v2 было два канала, default и experimental. В Fill их три, и у каждой сборки есть свой:

КаналЧто это значит
STABLEСборки, которые PaperMC рекомендует для продакшена
BETAФункционально завершены для этой версии, но ещё дорабатываются
ALPHAРанние сборки новой версии Minecraft

Новый релиз Minecraft начинает жизнь как череда сборок ALPHA, переходит в BETA, когда ими уже можно пользоваться, и становится STABLE, когда PaperMC им довольна. Для 26.3 на момент написания было 48 альфа-сборок, 38 бета-сборок и 15 стабильных, и это даёт представление о том, как долго длится нестабильный период. Релиз-кандидаты вроде 26.3-rc-3 могут так и не получить стабильной сборки.

Документация PaperMC говорит об этом прямо: используйте стабильные сборки и не запускайте нестабильные сборки и автообновление в продакшене, потому что экспериментальные сборки подвержены ошибкам и поддержки не получают. Это стоит понимать буквально. На сообщение в Discord, которое начинается со слов "я на альфа-сборке", отвечают одним и тем же.

Фильтр channel в списке сборок принимает и несколько значений (?channel=STABLE&channel=BETA), что удобно для тестового сервера, который должен проверять беты до того, как они дойдут до продакшена.

Этикет User-Agent и почему теперь это правило#

В v2 User-Agent был вежливостью. В Fill он обязателен. В документации PaperMC по загрузкам сказано, что каждый запрос должен содержать User-Agent, который чётко называет ваше программное обеспечение или организацию, не является общим значением по умолчанию вроде curl/8.5.0 или Wget/1.21 и содержит URL или адрес электронной почты для связи. Их собственный пример - тот, что использует популярный Docker-образ:

code
mc-image-helper/1.39.11 (https://github.com/itzg/docker-minecraft-server)

Запрос без него сегодня вполне может сработать, особенно если ответ отдаётся из кеша, но полагаться на это значит строить на том, что операторы прямо не разрешают, а заблокированный скрипт ломается так же непонятно, как при отключении v2. Формат, удовлетворяющий правилу, - name/version (contact):

bash
$ curl -A "smp-updater/1.2 (admin@example.net)" \    https://fill.papermc.io/v3/projects/paper

Остальной этикет вытекает из той же идеи: API - бесплатный сервис, который поддерживают волонтёры, и скрипты, которые его бомбардируют, и есть причина, по которой появляются такие правила.

  • Не опрашивайте постоянно. Проверки раз в сутки или раз перед каждым плановым перезапуском вполне достаточно. Paper может выпустить несколько сборок за один вечер; получать каждую из них в течение нескольких минут не нужно.
  • Не скачивайте то, что у вас уже есть. Сравните id сборки (или sha256) с установленным и остановитесь, если они совпадают. Скрипт ниже так и делает.
  • Учитывайте заголовки кеша. Ответы с метаданными содержат cache-control: max-age=1800. Если спрашивать чаще, чем раз в полчаса, вы получите тот же ответ.
  • Скачивайте jar один раз на машину, а не при каждом запуске сервера. Если сеть запускает восемь бэкендов на одной машине, нужно скачать один jar и скопировать его.

Закрепить сборку или следовать за последней#

Под словами "обновить Paper" можно понимать две совершенно разные вещи, и автоматизировать скрипту стоит только одну из них.

Сборки внутри одной версии Minecraft - это в основном исправления ошибок и работа над производительностью. Переход со сборки 187 на 189 версии 26.3 не конвертирует мир и не меняет API плагинов, и скрипт, который следует за последней стабильной сборкой фиксированной версии, для многих серверов разумен. Но и здесь изредка сборка меняет поведение, на которое опирался плагин, или закрывает то, чем злоупотребляли, - недавняя сборка 26.3, которая запретила плагинам сбрасывать рецепты варки вне основного потока, как раз такое изменение. Для небольшого сервера для друзей еженедельное следование стабильным сборкам нормально. Для сервера с десятками плагинов закрепите сборку, которую вы проверили, и переходите на новую осознанно.

Новая версия Minecraft - совсем другое событие. Мир конвертируется при первой загрузке, и старая версия уже не сможет его открыть, плагины, собранные под старую версию, часто ломаются, а клиенты должны соответствовать. Это ни в коем случае не должно происходить из-за того, что скрипт заметил новую запись вверху списка версий. Держите версию Minecraft как фиксированную настройку, которую выбирает человек, и когда будете её менять, пройдите по статье обновление версии Minecraft.

На практике закрепить значит записать сборку. Либо храните точный id сборки в конфигурационном файле, и скрипт ставит именно его, либо пусть скрипт следует за стабильными сборками, но записывает каждую установку в журнал, чтобы вы знали, к какой сборке вернуться. Эндпоинт версии перечисляет все существующие id сборок, поэтому закреплённый id остаётся доступным. Храните предыдущий jar рядом с текущим: откат сборки внутри той же версии Minecraft - это переименование файла, если мир ещё не был конвертирован.

Скрипт обновления на curl и jq#

Этот скрипт устанавливает новейшую стабильную сборку одной фиксированной версии Minecraft или закреплённую сборку, если вы её укажете. Он проверяет контрольную сумму до того, как тронет рабочий jar, хранит предыдущий jar для отката и вообще ничего не делает, если установленная сборка уже актуальна. Нужны bash, curl, jq и sha256sum.

update-paper.sh
#!/usr/bin/env bash# Usage: update-paper.sh <minecraft-version> [build]set -euo pipefailPROJECT="${PROJECT:-paper}"            # paper, folia or velocityVERSION="${1:?usage: $0 <minecraft-version> [build]}"PIN="${2:-}"                           # optional exact build idDIR="${DIR:-/home/mc/server}"JAR="$DIR/server.jar"STATE="$DIR/.${PROJECT}-build"UA="smp-updater/1.2 (admin@example.net)"API="https://fill.papermc.io/v3/projects/$PROJECT/versions/$VERSION"if [[ -n "$PIN" ]]; then  build=$(curl -fsS -A "$UA" "$API/builds/$PIN")else  build=$(curl -fsS -A "$UA" "$API/builds?channel=STABLE" | jq -e '.[0]') \    || { echo "No stable $PROJECT build for $VERSION" >&2; exit 1; }fiid=$(jq -r '.id' <<<"$build")url=$(jq -r '.downloads."server:default".url' <<<"$build")sha=$(jq -r '.downloads."server:default".checksums.sha256' <<<"$build")name=$(jq -r '.downloads."server:default".name' <<<"$build")if [[ -f "$STATE" && "$(cat "$STATE")" == "$id" ]]; then  echo "$PROJECT $VERSION build $id already installed"; exit 0fitmp=$(mktemp "$DIR/.download.XXXXXX")trap 'rm -f "$tmp"' EXITcurl -fsS -A "$UA" -o "$tmp" "$url"echo "$sha  $tmp" | sha256sum -c --quiet -[[ -f "$JAR" ]] && cp -p "$JAR" "$JAR.prev"mv "$tmp" "$JAR"echo "$id" > "$STATE"echo "$(date -Is) installed $name" >> "$DIR/update.log"

Запустите ./update-paper.sh 1.21.11, чтобы следовать за стабильными сборками 1.21.11, или ./update-paper.sh 1.21.11 132, чтобы установить ровно сборку 132. Тот же скрипт работает с Velocity и Folia через переменную PROJECT:

bash
$ PROJECT=velocity DIR=/home/mc/proxy ./update-paper.sh 4.2.0$ PROJECT=folia ./update-paper.sh 26.3

Зачем нужна каждая деталь:

  • curl -f превращает ошибку HTTP в ненулевой код выхода, так что 410, 404 или заблокированный запрос останавливают скрипт, а не создают JSON-файл, названный как jar. -sS убирает лишний вывод, но настоящие ошибки всё равно показывает.
  • jq -e '.[0]' завершается с ненулевым кодом, если массив пуст - то есть у версии ещё нет стабильных сборок, - поэтому скрипт останавливается с сообщением, а не запрашивает URL null.
  • Загрузка идёт во временный файл в той же папке и заменяет рабочий jar только после успешной проверки контрольной суммы. Если писать прямо поверх server.jar, обрыв соединения оставит обрезанный jar и сервер, который не запустится. Временный файл на той же файловой системе делает финальный mv атомарным.
  • sha256sum -c ожидает два пробела между хешем и именем файла. С одним пробелом он сообщает об ошибке формата, а не о несовпадении, и это частая ошибка при копировании.
  • Файл состояния хранит id установленной сборки, поэтому при повторном запуске подряд второй раз ничего не скачивается.

Запускайте скрипт при остановленном сервере или хотя бы перезапускайте сервер сразу после: JVM держит старый jar открытым, а Paper читает пропатченные классы из каталога кеша, который создаёт при первом запуске. Новая сборка вступает в силу при следующем запуске, когда Paperclip замечает новый jar и патчит его заново, и это добавляет несколько секунд к первой загрузке.

На macOS sha256sum может отсутствовать; shasum -a 256 -c принимает те же входные данные. В Windows аналогичная проверка - Get-FileHash -Algorithm SHA256 в PowerShell, результат сравнивают с полем sha256.

Особенности Folia и Velocity#

API одинаков для двух других проектов, но то, что вы делаете с результатом, - нет.

Версии Velocity - это собственные номера версий прокси, а не версии Minecraft. В проекте есть семейства 4.0.0 и 3.0.0 с записями вроде 4.2.0, 3.5.0 и 3.6.0-SNAPSHOT. У snapshot-версий много сборок, у релизных очень мало: у 4.2.0 на момент написания была единственная сборка с номером 30, а у некоторых старых релизных id, например 3.5.0, сборок нет вовсе, так что проверяйте, прежде чем закреплять такой id. Версия прокси не зависит от версии бэкенда, и одна сборка Velocity обычно поддерживает диапазон версий клиентов, поэтому обновлять её менее хлопотно, чем Paper, - но обновление прокси всё равно разом прерывает игру всем игрокам сети. Планируйте его заранее и не позволяйте ему происходить по таймеру вечером. Учтите и то, что линейка 4.x требует Java 25. О том, как прокси и бэкенды работают вместе, рассказывает статья сеть на прокси Velocity.

У Folia версий и сборок гораздо меньше, чем у Paper, и только для тех версий, на которые PaperMC её портировала. Реальное ограничение - совместимость плагинов: обновление Folia важно меньше, чем вопрос, заявляют ли ваши плагины поддержку Folia вообще. Закрепляйте сборки Folia и тестируйте их, как подробнее объясняет статья региональная многопоточность Folia.

Форки вроде Purpur и Pufferfish не входят в API PaperMC. У них свои сервисы загрузки со своими схемами URL; что они меняют и зачем они могут понадобиться, описано в статье форки Purpur и Pufferfish.

Запуск по расписанию без последствий#

Сам по себе скрипт безопасен. Опасной автоматизацию делает то, когда она запускается и что происходит дальше. Разумная схема на самостоятельно управляемой машине с Linux выглядит так:

  1. Сначала всегда, каждый раз, делается резервная копия мира. Сборка, которая портит чанк, - редкость, но редкость не значит "никогда", а резервная копия обходится дёшево. Что в неё включать, описано в статье резервные копии и восстановление мира Minecraft.
  2. Запускается скрипт обновления с фиксированной версией Minecraft и стабильным каналом.
  3. Сервер перезапускается в тихий час после предупреждения в чате.
  4. Что-то проверяет, что сервер поднялся, - строка журнала Done (...)! For help, type "help" в течение нескольких минут после старта - и оповещает человека, если этого не произошло.
crontab
# 04:30 daily: back up, update within 1.21.11, restart30 4 * * * /home/mc/backup.sh && /home/mc/update-paper.sh 1.21.11 && systemctl restart minecraft

Цепочка && важна: нет резервной копии - нет обновления; сбой загрузки или контрольной суммы - нет перезапуска. Общую политику - какие серверы могут обновляться сами, а какие нет - разбирает статья автоматизация обновлений игровых серверов, а сторону перезапуска - статья расписания перезапусков, которые помогают.

На RE:NODE серверы Minecraft устанавливаются с Paper и подходящей версией Java, с принятым EULA и созданным миром, так что первая загрузка уже сделана за вас. Заменить jar позже - это операция с файлами: загрузите проверенную вами сборку через файловый менеджер или SFTP (SFTP и файловый менеджер рассказывает подробнее), а вкладка Schedules может выстроить по порядку резервную копию, предупреждение в чате и перезапуск с задержками между ними. Слоты резервных копий входят в каждый тариф Minecraft, так что шаг перед обновлением - это одна кнопка.

Разбор ошибок, которые встречаются на самом деле#

`Error: Invalid or corrupt jarfile server.jar`. Файл - не jar. Выполните head -c 200 server.jar: если он начинается с {"ok":false, то URL был старым адресом v2 или запрос отклонили. Перейдите на эндпоинты v3 и добавьте -f в curl, чтобы это больше не происходило молча.

`410 Gone` с `"error":"sunset"`. Вы обращаетесь к api.papermc.io/v2. Исправить это можно только переходом на fill.papermc.io/v3. Проверьте скрипты, Dockerfile, роли Ansible и все стартовые скрипты, которые что-то скачивают при загрузке: о них обычно забывают, потому что годами они работали.

`jq: error: Cannot index array with "downloads"`. Вы запросили список сборок, а обработали результат как одну сборку. Список - это массив; сначала возьмите .[0]. Эндпоинты одной сборки (builds/189, builds/latest) возвращают объект.

Скрипт установил альфу. Он использовал builds/latest, который игнорирует каналы. Используйте builds?channel=STABLE и первый элемент.

Пустой массив от `?channel=STABLE`. У версии ещё нет стабильных сборок - это обычное дело неделю и дольше после выхода Minecraft и постоянное состояние для релиз-кандидатов. Подождите или оставайтесь на предыдущей версии. Не переключайтесь на альфу автоматически.

`sha256sum: WARNING: 1 computed checksum did NOT match`. Загрузка оборвалась или была изменена по дороге. Не устанавливайте её: удалите файл и скачайте заново. Если ошибка повторяется, сравните размер файла с полем size в JSON сборки - обычно виноват прокси или captive portal по пути.

`UnsupportedClassVersionError` после обновления. Вы перешли на версию Minecraft, для jar которой нужна более новая Java: для 26.x нужна Java 25. Перед установкой прочитайте java.version.minimum из эндпоинта версии.

FAQ#

Работает ли старый URL api.papermc.io v2 для старых сборок?

Нет. Каждый путь v2, включая прямые загрузки jar сборок, опубликованных годы назад, возвращает 410 Gone. Старые сборки по-прежнему доступны через v3: эндпоинт версии перечисляет все id сборок, а в JSON каждой сборки есть ссылка на скачивание.

User-Agent действительно обязателен или только рекомендуется?

В документации PaperMC сказано, что каждый запрос должен содержать User-Agent, который называет ваше программное обеспечение и даёт контакт, и что общие значения по умолчанию вроде curl/... неприемлемы. На некоторые запросы без него могут по-прежнему отвечать, но строить на этом скрипт не стоит.

Должен ли скрипт сам выбирать новейшую версию Minecraft?

Нет. Новая версия Minecraft необратимо конвертирует мир, ломает плагины и требует от каждого игрока обновить клиент. Автоматизируйте сборки внутри выбранной вами версии, а версию меняйте сами, с резервной копией.

Как получить ссылку на конкретную старую сборку Paper?

Запросите https://fill.papermc.io/v3/projects/paper/versions/<version>/builds/<build> и прочитайте .downloads."server:default".url. Не пытайтесь собрать URL из версии и номера сборки: в v3 путь содержит контрольную сумму файла, поэтому угадать его нельзя.

Следует ли Velocity номерам версий Minecraft?

Нет. Версии Velocity (3.5.0, 4.2.0 и так далее) - это собственные релизы прокси, и каждый из них поддерживает диапазон версий клиентов. Диапазон смотрите в примечаниях к выпуску, а не подбирайте по номерам.

Стоит ли проверка контрольной суммы лишней строки?

Да. Это разница между сервером, который отказывается обновляться, и сервером, который отказывается запускаться. Обрезанная загрузка встречается гораздо чаще подделки, а ловит обе одна и та же строка.