source.unsplash.com прекратил работу: разбор причин и все способы замены
Устарел в 2021 году с формулировкой «существующие реализации продолжат работать», отключён в июне 2024-го, но всё ещё встречается в новом коде сегодня. Взвешенный разбор причин — и три замены, включая прокси, который возвращает случайность без ключа.
Сервис стоковых фотографий отключил один поддомен, и спустя два года он по-прежнему ломает документацию, экраны входа, учебные примеры и только что сгенерированный код. Это разбор истории одного URL — что он делал, что его убило и чем его заменить, — а также трезвый взгляд на более странную часть истории: машины, пишущие за нас код, до сих пор не заметили, что его больше нет.
HTTP-ответы, обе записи changelog, процитированные дословно, лимиты API, трекеры задач сломанных проектов и подсчёты по GitHub, npm и Stack Overflow — всё это взято из первоисточников, с методикой проверки для каждого пункта в примечаниях. Если вам нужен только фикс, переходите сразу к таблице миграции.
Что вы получите сегодня, если всё же обратитесь по этому адресу
Одна команда, без ключа, воспроизводимая на любой машине:
curl -I https://source.unsplash.com/random
HTTP/2 503
cache-control: no-cache, no-store
content-type: text/html; charset=utf-8
server: Heroku
via: 2.0 heroku-router
# тело ответа: iframe, указывающий на herokucdn.com/error-pages/application-error.html
Ни о какой ошибке DNS речи не идёт. source.unsplash.com по-прежнему резолвится — это
CNAME на хост herokudns.com, — так что запрос получает ответ, просто не от
приложения. Эта деталь важнее, чем кажется на первый взгляд: браузер, получивший быстрый
503 с телом в HTML, отрисовывает плейсхолдер битого изображения, а любой код,
проверяющий response.ok или обработчик onerror, который вы никогда не
писали, уходит по ветке ошибки, которую вы никогда не тестировали.
| Шаблон URL | Что раньше возвращал | Сегодня |
|---|---|---|
source.unsplash.com/random | Случайное фото любого размера | 503 |
source.unsplash.com/random/1600x900 | Случайное фото, обрезанное под размер | 503 |
source.unsplash.com/1600x900/?apple,desk | Случайное фото по поисковым словам | 503 |
source.unsplash.com/featured/1600x900?nature | Случайное подборочное (featured) фото | 503 |
source.unsplash.com/collection/190727/800x600 | Случайное фото из коллекции | 503 |
source.unsplash.com/user/scottwebb/1600x900 | Случайное фото одного автора | 503 |
source.unsplash.com/daily | Фото дня | 503 |
Проверено по отдельности с помощью curl -o /dev/null -w "%{http_code}". Функция поиска
была отключена первой, как и было объявлено; сегодня приложение выключено целиком, так что это
различие уже не имеет значения.
Три года между «устарело» и «отключено»
Оба объявления по-прежнему читаются, в одном месте, по адресу unsplash.com/documentation/changelog. Приведены полностью, потому что вся суть истории — в формулировках:
25 ноября 2021 — «Unsplash Source being deprecated»
«Unsplash Source устаревает. Существующие реализации продолжат работать, однако для новых проектов используйте полноценный Unsplash API».
11 июня 2024 — «Unsplash Source sunset»
«Unsplash Source официально не поддерживается с момента объявления об устаревании в 2021 году. В рамках окончательного отключения мы сначала свернём функцию поиска, а в ближайшие недели полностью отключим приложение. Существующие реализации Source — в особенности продакшн-уровня — следует как можно скорее перевести на полноценный Unsplash API».
Прочитайте их подряд — и механизм провала становится очевидным. В уведомлении 2021 года содержалось обещание (существующие реализации продолжат работать) и не было даты. У разработчика, прочитавшего его в 2021 году, были все основания оставить рабочий код без изменений; разработчик, присоединившийся к проекту в 2022-м, вообще никогда его не читал. Уведомление 2024 года дало «ближайшие недели» — спустя три года, на странице, которую никто не сохранял в закладках.
У Unsplash действительно есть опубликованная политика устаревания, и она вполне разумна —
документация гласит, что для публично задокументированных полей и эндпоинтов изменения объявляются
в changelog как минимум за 3 недели, а сами эндпоинты в период устаревания
возвращают заголовок Warning. В том же абзаце есть фраза, которая объясняет, почему
ничто из этого не защитило Source: «Для любых не задокументированных публично полей или
эндпоинтов мы можем вносить изменения без предупреждения». Source никогда не был эндпоинтом
документированного API. Он находился за пределами политики, которая могла бы его защитить.
- Практический урок здесь не в том, что «Unsplash поступил безответственно». Урок в том, что URL, который можно использовать без чтения какой-либо документации, — это URL, политику устаревания которого вы тоже не читали.
- Поломка началась раньше объявления. Задача в трекере Drupal, заведённая 28 ноября 2022, уже сообщает «постоянно получаю ошибку приложения Heroku» — за восемнадцать месяцев до записи об отключении. Именно так и умирают подобные сервисы: медленно, а потом — в объявлении, которое вы никогда не увидите.
Объявление найти сложнее, чем саму поломку
Об устаревании 2021 года было объявлено на changelog.unsplash.com, и именно на этот
URL ссылается каждый современный ему баг-репорт — включая упомянутый выше отчёт Drupal. Три
измерения:
- HTTPS-эндпоинт сломан. Команда
openssl s_client -connect changelog.unsplash.com:443возвращаетtlsv1 alert internal error— рукопожатие не проходит ещё до предъявления какого-либо сертификата. Поэтому любая ссылка эпохи 2021 года, начинавшаяся сhttps://, в браузере уже не работает. - По обычному HTTP происходит редирект, но бесполезный. Переход по адресу
http://changelog.unsplash.com/deprecations/2021/11/25/source-deprecation.htmlзаканчивается, спустя два перехода, ошибкой400наunsplash.com/@documentation/changelog/deprecations/2021/11/25/source-deprecation/html— путь был поглощён маршрутом сайта для имён пользователей. - В архиве образовалась дыра ровно там, где произошло отключение. Последний успешный снимок старого changelog в Wayback Machine датирован 24 марта 2024; первый снимок нового — 23 августа 2024. Об отключении объявили 11 июня 2024 года — как раз внутри этого пятимесячного разрыва.
Ничего из этого не заговор; это обычная миграция CMS. Но последствие вполне реально, и именно поэтому эта статья цитирует обе записи полностью: первоисточник записи об устаревании должен пережить то, что он объявляет устаревшим, а здесь он чуть было не исчез.
Что именно сломалось
Не побочные проекты. Приведённые ниже поломки — это публичные записи в трекерах задач; заголовки, даты и статусы взяты из API GitHub и drupal.org.
| Проект | Задача | Открыта | Что в ней сказано |
|---|---|---|---|
| MUI (Material UI) | #42736 | 24 июня 2024 | «[docs] Random Unsplash photo URL is no longer functional» — официальный шаблон Sign-in side поставлялся с мёртвым изображением. Закрыта спустя три дня. |
| Nextcloud | #115 | 17 янв 2023 | «Migrate to Unsplash API» — приложение с фоновыми изображениями было построено на URI Source. Оставалась открытой восемнадцать месяцев, закрыта 16 июля 2024. |
| sindresorhus/Actions | #248 | 28 мая 2024 | «Get Unsplash Image: 503 Error» — действие для Shortcuts в iOS/macOS, сломалось за две недели до объявления об отключении. |
| Drupal — Gin Login | #3324054 | 28 ноя 2022 | «Unsplash отключил source.unsplash.com — это задерживает загрузку reCAPTCHA, из-за чего пользователи не могут войти». |
Перечитайте последнюю строку ещё раз — именно её стоит запомнить. Декоративное изображение рядом с формой входа — самый очевидно некритичный элемент на странице — переросло в сбой аутентификации, потому что медленный запрос к стороннему сервису оказался перед CAPTCHA, необходимой форме входа. Никто не проектировал это специально. Это возникло из-за порядка, в котором браузер загружает элементы страницы.
Ваш ИИ-ассистент по написанию кода не получил уведомление
Вот часть, которая превращает сбой 2024 года в проблему 2026-го. source.unsplash.com
документировали, обсуждали в блогах, преподавали и копировали примерно восемь лет. Весь этот текст
находится в обучающих данных моделей, которые сегодня пишут за нас стартовый код, — а текст не
устаревает сам по себе. Три подсчёта:
| Измерение | Значение на 30 авг 2026 | Как получено |
|---|---|---|
Файлы, содержащие source.unsplash.com |
3344 | API поиска по коду GitHub, q=source.unsplash.com (только проиндексированный
публичный код — нижняя граница, а не итог) |
| Репозитории в выборке из 100 файлов, созданные после отключения | 12 из 77 | Тот же запрос, 100 результатов, дедуплицировано до 77 репозиториев, created_at
сопоставлено с 11 июн 2024 |
| …и репозитории из этой выборки, в которые был пуш за последние 12 месяцев | 20 из 77 | Действующие репозитории, не архивы — включая elastic/kibana, чей демо-файл
по-прежнему содержит imageUrl: 'https://source.unsplash.com/64x64/?dingo' |
Ежемесячные загрузки unsplash-source-es6 |
23 | API реестра npm — обёртка для мёртвого сервиса, последний раз опубликованная в 2022 году, но всё ещё устанавливаемая |
| Посты на Stack Overflow с упоминанием | 1459 | API Stack Exchange, итог /search/excerpts |
Самое прямое свидетельство находится не в коде приложений — оно в промптах. Первый результат по этому запросу — библиотека системных промптов GPT со строкой «please use unsplash API( https://source.unsplash.com/1280x720/?<PUT YOUR QUERY HERE>» («используй unsplash API»). Эта инструкция до сих пор копируется в новых ассистентов. Модель не проверяет URL — ей было сказано его использовать, и каждый пример, который она когда-либо видела, подтверждал это же.
Таким образом у сбоя в сгенерированном коде две независимые причины, и исправление одной не устраняет другую: устаревшие обучающие данные и устаревшие инструкции, написанные людьми поверх них. В любом случае симптом один и тот же — семейство изображений, которые никогда не загружаются:
source.unsplash.com/random/1200x800 # 503 с середины 2024 — уже не заработает
images.unsplash.com/photo-… # реальный CDN, но заученные ID могут не существовать
via.placeholder.com/400 # серый прямоугольник, попавший в продакшн
placehold.co/800x600 # серый прямоугольник, намеренно
picsum.photos/800/600 # реальное фото, не связанное с вашей страницей
/placeholder.png # файл, который так и не добавили в репозиторий
Примечание ко второй строке этого списка: во время подготовки статьи via.placeholder.com
тоже не завершил TLS-рукопожатие в нашей тестовой сети и ответил 403 по обычному HTTP.
Проверьте его из своей собственной сети, прежде чем на него полагаться, — у запасного варианта,
к которому прибегают эти инструменты, может быть своя собственная история сбоев.
Только первый вариант в списке по-настоящему сломан. Остальные хуже, но менее заметно: они загружаются, вёрстка выглядит завершённой, и никто не замечает, что страница проиллюстрирована чем попало. И это касается не только изображений — это общая форма проблемы. Представление модели об интернете — это снимок момента, а эндпоинты, флаги CLI, названия пакетов и бесплатные тарифы продолжают меняться уже после того, как затвор закрылся.
Таблица миграции
Есть ровно три пункта назначения, и честный способ их представить — через то, чем вы жертвуете. Сначала выберите столбец, затем читайте свою строку.
| Старый URL Source | A. Фиксированный URL CDNбез ключа · без случайности | B. Unsplash APIключ · вызов с сервера | C. Собственный проксиключ скрыт · случайность возвращена |
|---|---|---|---|
/random |
images.unsplash.com/photo-… — одно выбранное вами фото |
GET /photos/random |
/?w=1600 |
/random/1600x900 |
…?w=1600&h=900&fit=crop |
/photos/random + параметры Imgix к возвращённому URL |
/?w=1600&h=900&fit=crop |
/1600x900/?apple,desk |
Аналога нет — выбирайте фото вручную | /photos/random?query=apple,desk |
/?query=apple,desk&w=1600 |
/featured/1600x900?nature |
Аналога нет | /photos/random?query=nature у «featured» нет преемника |
/?query=nature&w=1600 |
/collection/67920491/1600x900 |
Аналога нет | /photos/random?collections=67920491 |
/?collections=67920491&w=1600 |
/user/scottwebb/1600x900 |
Аналога нет | /photos/random?username=scottwebb |
/?username=scottwebb&w=1600 |
/daily |
Зафиксируйте одно фото, меняйте его при сборке | Аналога нет — кешируйте одно случайное фото на 24 ч самостоятельно | То же самое, но кеш внутри прокси |
Вариант A — тот, который на самом деле нужен большинству. Если изображение носило декоративный характер — hero-баннер, боковая панель на экране входа, фон карточки, — вам никогда и не требовалось разное фото при каждом запросе. Выберите одно, сохраните URL CDN, и страница перестанет зависеть от чего-либо случайного:
<img src="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=1600&h=900&fit=crop&auto=format"
width="1600" height="900" alt="…">
# Официально поддерживаемые параметры: w, h, crop, fit, fm, auto=format, q, dpr.
# Сохраняйте параметр ixid, полученный от API, — именно он учитывает просмотр.
Вариант B — официальный путь, и он переносит вызов на сторону сервера, поскольку
Client-ID во фронтенд-JavaScript — это опубликованный ключ доступа. Обратите внимание
на два правила, о которые чаще всего спотыкаются: collections/topics
нельзя сочетать с query в одном запросе, а параметр count (максимум 30)
меняет форму ответа на массив, даже если значение равно 1.
curl "https://api.unsplash.com/photos/random?query=nature&orientation=landscape" \
-H "Authorization: Client-ID YOUR_ACCESS_KEY" \
-H "Accept-Version: v1"
# → JSON. Изображение находится в .urls.regular / .urls.raw (w/h/fit добавляйте сами).
# → X-Ratelimit-Limit: 1000 X-Ratelimit-Remaining: 999
Вариант C: воссоздать Source примерно за сорок строк
Если вы потеряли именно поведение — бесключевой URL, возвращающий каждый раз другое фото, готовый
к использованию прямо в теге <img>, в поле CMS или на статичном сайте, где
нет сервера, — придётся запускать этот эндпоинт самостоятельно. Это один небольшой воркер перед
API, и три вещи, которые позволяют ему выжить в продакшне, — это кеш, проверка referrer'а и
передача остальной части query-строки в CDN без изменений.
// Cloudflare Workers. В других местах (Deno Deploy, Val Town…) структура та же,
// но именованный кеш открывайте через caches.open(), а не caches.default.
// UNSPLASH_KEY остаётся на сервере. Вызывающие его никогда не видят.
const ALLOWED = ["example.com", "www.example.com"]; // только ваши домены
const API_PARAMS = ["query", "collections", "topics", "username", "orientation"];
const TTL = 60; // секунды — защищает часовую квоту
const host = (value) => { try { return new URL(value).hostname; } catch { return null; } };
export default {
async fetch(req, env, ctx) {
// 0. Только GET: Cache API отказывается кешировать что-либо ещё, а у эндпоинта
// изображений и нет других глаголов для ответа.
if (req.method !== "GET")
return new Response("Method not allowed", { status: 405 });
const url = new URL(req.url);
// 1. Встраивать может только ваш собственный сайт — публичный эндпоинт
// случайных фото в открытом интернете сжигает чужой лимит запросов.
const ref = req.headers.get("referer"); // у многих легитимных клиентов его нет
if (ref && !ALLOWED.includes(host(ref)))
return new Response("Forbidden", { status: 403 });
// 2. Кешируем по комбинации параметров, чтобы страница с 12 изображениями
// стоила один вызов API в минуту, а не двенадцать на каждый рендер.
const cache = caches.default;
const hit = await cache.match(req);
if (hit) return hit;
// 3. Запрашиваем случайное фото у официального API.
const api = new URL("https://api.unsplash.com/photos/random");
for (const p of API_PARAMS)
if (url.searchParams.has(p)) api.searchParams.set(p, url.searchParams.get(p));
const r = await fetch(api, { headers: {
Authorization: "Client-ID " + env.UNSPLASH_KEY,
"Accept-Version": "v1",
}});
// 403 здесь обычно означает часовую квоту, а не плохой ключ — увеличьте TTL, не паникуйте.
if (!r.ok) return new Response("Upstream " + r.status, { status: 502 });
const photo = await r.json();
// 4. Пересобираем URL изображения: сохраняем ixid, добавляем параметры размера от клиента.
const img = new URL(photo.urls.raw); // .raw уже содержит ixid
for (const [k, v] of url.searchParams)
if (!API_PARAMS.includes(k)) img.searchParams.set(k, v); // w, h, fit, q…
const res = new Response(null, { status: 302, headers: {
Location: img.toString(),
"Cache-Control": "public, max-age=" + TTL,
// Указание автора идёт вместе с редиректом; значения заголовков должны быть ASCII, отсюда кодирование.
"X-Photo-Credit": encodeURIComponent(photo.user.name + " on Unsplash"),
"X-Photo-Link": photo.links.html,
}});
ctx.waitUntil(cache.put(req, res.clone()));
return res;
},
};
Тогда миграция URL сводится к поиску с заменой, и именно это делает данный вариант достойным потраченных двадцати минут:
- https://source.unsplash.com/collection/67920491/1600x900
+ https://img.example.com/?collections=67920491&w=1600&h=900&fit=crop
Два замечания по проектированию, каждое из которых стоило кому-то испорченного вечера, прежде чем
их наконец записали. Редирект (302) вместо проксирования байтов снимает с вас нагрузку
по трафику и сохраняет учёт просмотра на стороне CDN Unsplash, чего и требуют правила
использования. А проверка Referer намеренно снисходительна, если заголовок
отсутствует, — многие легитимные клиенты его удаляют, — но при этом всё же блокирует очевидный
случай, когда ваш эндпоинт превращается в чужой бесплатный API изображений.
Правила, которые вы наследуете в тот же момент, когда начинаете использовать API
У Source не было правил, потому что не было аккаунта. У API их пять, и они меняют архитектуру вашего решения; все — из текущей документации:
- Лимиты запросов почасовые и поначалу небольшие. 50 запросов/час
в демо-режиме; 1000/час после одобрения вашего приложения для продакшна. Учитываются
только вызовы к
api.unsplash.com— запросы изображений кimages.unsplash.comне считаются. ЧитайтеX-Ratelimit-Remainingв каждом ответе. - Прямые ссылки (hotlinking) обязательны, а не просто разрешены. Unsplash требует, чтобы URL изображений, возвращаемые API, встраивались напрямую — так просмотры можно засчитывать автору фото. Зеркалирование файла на собственный CDN — единственная оптимизация, которую вам не разрешено делать.
- Сохраняйте параметр
ixid. Изменение размера и обрезка возвращённого URL ожидаемы; удаление параметра, идентифицирующего ваше приложение, — нет. - Атрибуция и учёт скачиваний — часть договора — автору фото и Unsplash полагается указание источника, а «скачивание» фиксируется через эндпоинт скачивания фото, когда пользователь забирает файл, — это событие вам придётся отправлять самостоятельно.
- Распространяемым продуктам нужна динамическая регистрация клиента. Если вы поставляете плагин, тему или CMS с самостоятельным хостингом, один общий ключ — это одновременно нарушение правил и единая точка отказа; у API как раз для такого случая есть отдельный поток регистрации.
Самое время честно очертить рамки: если уж вы всё равно подключаете API и ключ, выбор какого именно API изображений внезапно становится открытым, и стоит потратить пять минут на этот выбор, прежде чем писать клиент. Мы сравнили бесплатные варианты — квоты, правила, поведение поиска и форматы ответов — в статье сравнение бесплатных API стоковых фотографий.
Если вам нужен был только плейсхолдер — так и скажите
Значительная доля обращений к Source вообще не имела отношения к Unsplash. Это было «поставить сюда что-то похожее на изображение, пока я собираю вёрстку». Для этого случая бесключевые сервисы по-прежнему существуют и являются правильным решением:
| Сервис | Ключ? | Что вы получаете | Где заканчиваются возможности |
|---|---|---|---|
| Lorem Picsum | Нет | Настоящие фотографии: picsum.photos/800/600, стабильный вариант через
/id/237/… или /seed/xxx/…, а также ?grayscale и
?blur=1..10. Эндпоинт /v2/list указывает страницу и автора каждого
фото на Unsplash. |
Никакого таргетинга по теме. Фото никак не связано с вашей страницей. |
| placehold.co | Нет | Подписанные прямоугольники любого размера — честный заполнитель для вайрфреймов. | Это серая коробка, и на скриншоте, отправленном клиенту, она выглядит именно так. |
| Openverse | Нет | Каталог со свободными лицензиями и публичным API, работающий силами WordPress.org. | Поиск по ключевым словам, и лицензии у каждого элемента разные — их нужно проверять самостоятельно. |
Важное различие: плейсхолдер по определению временен. Если изображение доживает до продакшна, оно уже не плейсхолдер — это иллюстрация, которую никто не выбирал, и читатель это чувствует.
Один ключ вместо трёх
Вот часть миграции, к которой никто не готовится: те, кто уходит от Source, редко останавливаются
на одном API. Странице нужен hero-баннер, два изображения для разделов и что-то для сетки
карточек, и честный ответ обычно — Unsplash плюс Pexels плюс Pixabay: три
регистрации, три схемы авторизации, три формата JSON, три модели пагинации и три набора правил
атрибуции — и всё это ради заполнения одних и тех же тегов <img>. Именно эта
интеграционная работа и есть настоящая цена исчезновения бесключевого URL, и она наступает спустя
недели после вызвавшего её сбоя.
Свести всё это к одной интеграции — вот для чего мы построили Pexafy: единый ключ для 9 библиотек со свободными лицензиями в одной схеме, с семантическим поиском на уровне предложений — так что полное описание вроде «треснувший экран телефона на деревянном столе, снято сверху» возвращает ранжированные результаты вместо пустоты. Два ограничения, сформулированные прямо, потому что вся эта статья посвящена тому, чтобы не удивляться дважды: для работы нужен ключ, а значит, сервис не восстанавливает то, чем был Source, — он относится к той же категории, что и официальный Unsplash API выше; и он предоставляет фотографии со свободными лицензиями, а не редакционные или брендовые изображения.
Действительно новая часть решения адресована ассистентам, описанным выше:
MCP-сервер по адресу mcp.pexafy.com/mcp означает, что модель, которая иначе процитировала
бы URL изображения по памяти, может выполнить поиск по реальному каталогу и вернуть фото, которое
действительно существует, вместе с прикреплённой строкой указания авторства. Это более удачный
ответ на порождённые машинами мёртвые URL, чем любое правило линтера, и обоснование изложено в
статье инфраструктура
поиска изображений для ИИ-агентов.
Проверьте своё хозяйство за десять минут
На что бы вы ни переходили, сначала сделайте вот это — вы не сможете исправить URL, которые не нашли. Source — лишь сегодняшний пример; те же три шага применимы к любому внешнему ресурсу, который вы встраиваете.
# 1. Всё в репозитории, включая документацию, тесты, фикстуры и README.
grep -rn --binary-files=without-match \
-e "source.unsplash.com" -e "via.placeholder.com" -e "/placeholder.png" .
# 2. Всё, что хранится в базе данных — тексты CMS дольше всего скрывают такое.
psql -c "SELECT id FROM posts WHERE body LIKE '%source.unsplash.com%'"
# 3. Всё, что реально запрашивает собранный сайт: обойдите его и выведите список сбоев.
# Ищите по атрибуту, а не по расширению файла — URL изображений редко заканчиваются на .jpg.
grep -rhoE 'src="[^"]+"' dist/ \
| cut -d'"' -f2 | grep -E '^https?://' | sort -u \
| xargs -P8 -I{} curl -s -o /dev/null -w "%{http_code} {}\n" {} \
| grep -v "^200"
# 503 https://source.unsplash.com/random/1200x800 ← вот что вы ищете
А затем один раз решите, во сколько внешние изображения вправе вам обходиться. Четыре правила, которые переживут следующее отключение, кто бы его ни вызвал:
- Получайте изображение на этапе сборки, а не на этапе запроса. Изображение, разрешённое во время сборки, сломается в CI, на глазах у разработчика, а не в 3 часа ночи на глазах у пользователя.
- Никогда не давайте декоративному ресурсу блокировать критичный путь. Не
предзагружайте ничего внешнего над формой входа; снабдите каждый сторонний
<img>запасным вариантом черезonerrorи явнымиwidth/height, чтобы сбой стоил вам пустого прямоугольника, а не сдвига вёрстки или зависшего скрипта. - Добавьте проверку в CI. Шаг 3 выше, запущенный на собранном выводе, превращает «кто-то в конце концов заметил» в красную сборку. Это единственный шаг, который предотвращает повторение.
- Планируйте бюджет для внешних зависимостей так же, как для любых других. Зафиксируйте, от каких хостов вправе зависеть ваши страницы и что произойдёт, если каждый из них окажется недоступен. URL, для которого не нужно было регистрироваться, — всё равно зависимость; Source просто доказал, что это зависимость, которой никто не владеет.
Источники и примечания
1 Каждый код статуса, подсчёт и цитата в этой статье взяты из
первоисточника 30 августа 2026 года. Коды HTTP-статуса получены с
помощью curl для каждого шаблона URL; все возвращали 503 с
server: Heroku и телом, содержащим
herokucdn.com/error-pages/application-error.html. Резолвинг DNS подтверждён в тот же
день (CNAME на хост herokudns.com).
2 Обе записи changelog процитированы дословно из
unsplash.com/documentation/changelog. Формулировки политики устаревания (3 недели
уведомления, заголовок Warning, а также исключение для не задокументированных
публично эндпоинтов) взяты из unsplash.com/documentation в тот же день.
3 Ошибка TLS воспроизведена командой
openssl s_client -connect changelog.unsplash.com:443 (tlsv1 alert internal
error). Цепочка редиректов прослежена через curl -L. Разрыв в архиве взят из
CDX API Wayback: последний успешный (200) снимок changelog.unsplash.com
датирован 20240324, первый снимок unsplash.com/documentation/changelog — 20240823.
4 Заголовки задач, даты создания и закрытия взяты из REST API GitHub
(mui/material-ui#42736, nextcloud/unsplash#115,
sindresorhus/Actions#248) и из JSON API drupal.org для задачи 3324054 в
gin_login, в тексте которой сообщается «постоянно получаю ошибку приложения Heroku»
в ноябре 2022 года.
5 Подсчёты: API поиска по коду GitHub
(3344 файла; выборка из 100 результатов дедуплицирована до 77 репозиториев, из
которых 12 созданы после 11 июня 2024, а в 20 был пуш за предыдущие 12 месяцев); API
загрузок реестра npm (unsplash-source-es6, 23 загрузки за предыдущие 30 дней);
Stack Exchange /search/excerpts (1459 постов). Поиск по коду охватывает
только проиндексированные публичные репозитории, так что каждая цифра — нижняя граница.
Первоисточники: changelog Unsplash API · документация Unsplash API · правило атрибуции Unsplash · статус Unsplash · MUI #42736 · Nextcloud #115 · sindresorhus/Actions #248 · Drupal Gin Login #3324054 · Lorem Picsum · Openverse · документация Pexafy API и MCP.
Часто задаваемые вопросы
source.unsplash.com не работает или отключён навсегда?
/random, /1600x900/?query, /collection/…, /daily) теперь возвращает HTTP 503 со стандартной страницей ошибки Heroku Application Error. Хост-имя по-прежнему резолвится, поэтому сбой выглядит как битое изображение, а не сетевая ошибка.Чем напрямую заменить source.unsplash.com/random?
images.unsplash.com/photo-…?w=1600&h=900&fit=crop — не требует ключа, но всегда возвращает одну и ту же фотографию, что на самом деле и было нужно в большинстве декоративных случаев использования. Официальный API, GET https://api.unsplash.com/photos/random с заголовком Authorization: Client-ID, возвращает случайность, но вызывать его нужно на сервере. Собственный небольшой прокси перед этим эндпоинтом — единственный вариант, который снова даёт URL без ключа, который можно напрямую вставить в тег <img>.Почему ИИ-инструменты для написания кода в 2026 году всё ещё генерируют URL source.unsplash.com?
Можно ли всё ещё получить случайное фото Unsplash без API-ключа?
/photos/random, который требует Client-ID. У вас есть два пути без ключа: прокси, который вы размещаете сами, где ключ остаётся на сервере, а публичный URL выглядит как старый, либо сторонний сервис-заглушка вроде Lorem Picsum (picsum.photos/800/600), который отдаёт настоящие фотографии без ключа, но вообще без возможности задать тему.Позволяет ли API Unsplash скачивать и размещать изображения на своём сервере?
ixid при изменении размера или обрезке URL, указывать автора и Unsplash в качестве источника, а также вызывать эндпоинт скачивания фото, когда пользователь забирает файл. Зеркалирование файлов на собственный CDN — единственная оптимизация, которую вы делать не вправе.Почему уведомление об устаревании 2021 года не защитило существующих пользователей?
Warning — распространяется на публично задокументированные поля и эндпоинты, и тот же пункт гласит, что всё недокументированное может измениться без предупреждения. Source никогда не был документированным эндпоинтом API, поэтому оказался вне действия этой политики.Как найти все мёртвые URL source.unsplash.com в своём проекте?
grep -rn "source.unsplash.com" . — поскольку такие URL дольше всего живут в примерах кода. Сделайте запрос к базе данных, ведь тексты статей CMS — это место, где они прячутся (WHERE body LIKE '%source.unsplash.com%'). Затем просканируйте собранный вывод: извлеките все URL изображений и запросите каждый, отметив всё, что вернуло не 200. Добавьте этот последний шаг в CI, и мёртвый сторонний ресурс будет ломать сборку, а не страницу.