source.unsplash.com गायब हो चुका है: पोस्ट-मॉर्टम और इसे बदलने के हर तरीके

2021 में “मौजूदा उपयोग काम करते रहेंगे” कहकर डिप्रिकेट किया गया, जून 2024 में पूरी तरह बंद कर दिया गया, और आज भी नए कोड में लिखा जा रहा है। एक तथ्यपरक पोस्ट-मॉर्टम — और तीन विकल्प, साथ ही वह प्रॉक्सी जो बिना-की के रैंडमनेस वापस लाता है।

साझा करें
एक हल्की लकड़ी की सतह पर पड़े टूटी स्क्रीन वाले स्मार्टफोन की ब्लैक-एंड-व्हाइट तस्वीर, क्षतिग्रस्त डिस्प्ले पर Unsplash का लोगो दिखाई दे रहा है।
फ़ोटो Unsplash के माध्यम से

एक स्टॉक फोटो सेवा ने एक सबडोमेन बंद कर दिया, और दो साल बाद भी यह डॉक्यूमेंटेशन साइट्स, लॉगिन स्क्रीन, कोर्स एक्सरसाइज़ और अभी-अभी जनरेट किए गए कोड को तोड़ रहा है। यह एक URL का पोस्ट-मॉर्टम है — यह क्या करता था, इसे किसने मारा, और इसकी जगह क्या रखें — साथ ही इस कहानी के अजीब हिस्से पर एक मापी-तुली नज़र: जो मशीनें हमारा कोड लिखती हैं, उन्हें अभी तक पता नहीं चला कि यह चला गया है।

HTTP रिस्पॉन्स, शब्दशः उद्धृत दोनों changelog एंट्रियाँ, API सीमाएँ, टूटे हुए प्रोजेक्ट्स के इश्यू ट्रैकर्स और GitHub, npm व Stack Overflow से लिए गए आंकड़े — ये सभी प्राथमिक स्रोतों से हैं, और हर एक की विधि फुटनोट्स में दी गई है। अगर आपको सिर्फ़ समाधान चाहिए, तो सीधे माइग्रेशन टेबल पर जाएँ।

आज अगर आप अभी भी इसे रिक्वेस्ट करें, तो क्या मिलता है

एक कमांड, बिना key के, किसी भी मशीन से दोहराने योग्य:

terminal
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
# body: herokucdn.com/error-pages/application-error.html की ओर इशारा करने वाला एक iframe

यहाँ कुछ भी DNS विफलता नहीं है। source.unsplash.com अभी भी resolve होता है — यह एक herokudns.com होस्ट का CNAME है — इसलिए रिक्वेस्ट का जवाब मिलता है, बस किसी एप्लिकेशन से नहीं। यह डिटेल जितनी मामूली लगती है, उससे कहीं ज़्यादा मायने रखती है: जिस ब्राउज़र को HTML बॉडी के साथ तेज़ 503 मिलता है, वह एक टूटी हुई इमेज का प्लेसहोल्डर दिखाता है, और जो भी कोड 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एक रैंडम फ़ीचर्ड फोटो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}" से की गई। सर्च फ़ीचर पहले बंद किया गया था, जैसा घोषित किया गया था; आज पूरा एप्लिकेशन बंद है, इसलिए यह अंतर अब मौजूद नहीं है।

“deprecated” और “off” के बीच तीन साल

दोनों घोषणाएँ अभी भी एक ही जगह पढ़ी जा सकती हैं, यहाँ: unsplash.com/documentation/changelog. पूरा उद्धृत किया गया है, क्योंकि शब्दांकन ही पूरी कहानी है:

25 नवंबर 2021 — “Unsplash Source being deprecated”
“Unsplash Source is being deprecated. Existing uses will continue to work, however for new projects use the full Unsplash API.”

11 जून 2024 — “Unsplash Source sunset”
“Unsplash Source has been officially unsupported since its deprecation in 2021. As part of the final sunsetting, we will first wind down by disabling the search feature, and in the coming weeks turn off the application entirely. Existing uses of Source — particularly production-level ones — should migrate as soon as possible to the full Unsplash API.”

इन्हें क्रम में पढ़ें तो विफलता का तरीका स्पष्ट हो जाता है। 2021 के नोटिस में एक वादा था (existing uses will continue to work) और कोई तारीख नहीं थी। जिस डेवलपर ने इसे 2021 में पढ़ा था, उसके पास काम कर रहे कोड को न छेड़ने की पूरी वजह थी; जो डेवलपर 2022 में जुड़ा, उसने इसे कभी पढ़ा ही नहीं। 2024 के नोटिस ने “coming weeks” कहा, तीन साल बाद, ऐसे पेज पर जिसे किसी ने बुकमार्क नहीं किया था।

Unsplash एक deprecation पॉलिसी प्रकाशित करता है, और वह उचित है — डॉक्यूमेंटेशन में कहा गया है कि सार्वजनिक रूप से दस्तावेज़ीकृत फ़ील्ड्स और एंडपॉइंट्स के लिए, बदलावों की घोषणा changelog पर कम से कम 3 सप्ताह की सूचना के साथ की जाती है, और deprecation अवधि के दौरान एंडपॉइंट्स एक Warning हेडर लौटाते हैं। उसी पैराग्राफ में वह वाक्य भी है जो बताता है कि इनमें से कुछ भी Source की रक्षा क्यों नहीं कर पाया: “For any non-publicly documented fields or endpoints, we may make changes to these with no warning.” Source कभी भी दस्तावेज़ीकृत API का एक एंडपॉइंट नहीं था। यह उस पॉलिसी के दायरे से बाहर था जो इसे कवर करती।

  • व्यावहारिक सबक “Unsplash लापरवाह था” नहीं है। सबक यह है कि जिस URL को आप बिना किसी डॉक्यूमेंटेशन पढ़े इस्तेमाल कर सकते हैं, उसकी deprecation पॉलिसी भी आपने नहीं पढ़ी होती।
  • टूटना घोषणा से पहले शुरू हो गया था। 28 नवंबर 2022 को दर्ज एक Drupal इश्यू पहले ही बताता है कि “I get always a Heroku application error”, सनसेट से अठारह महीने पहले। ये सेवाएँ इसी तरह मरती हैं: धीरे-धीरे, फिर एक ऐसी घोषणा में जिसे आप कभी देखते ही नहीं।

घोषणा outage से भी ढूँढना मुश्किल है

2021 वाली deprecation changelog.unsplash.com पर प्रकाशित हुई थी, और वही वह URL है जिससे उस समय की हर बग रिपोर्ट लिंक होती है — जिसमें ऊपर वाली Drupal रिपोर्ट भी शामिल है। तीन माप:

  1. HTTPS एंडपॉइंट टूटा हुआ है। openssl s_client -connect changelog.unsplash.com:443 tlsv1 alert internal error लौटाता है — किसी सर्टिफ़िकेट के पेश होने से पहले ही handshake विफल हो जाता है। इसलिए 2021-युग का हर लिंक, जो https:// था, ब्राउज़र में मृत है।
  2. सामान्य HTTP पर यह रीडायरेक्ट होता है, पर उपयोगी ढंग से नहीं। http://changelog.unsplash.com/deprecations/2021/11/25/source-deprecation.html को फॉलो करने पर, दो हॉप बाद, यह unsplash.com/@documentation/changelog/deprecations/2021/11/25/source-deprecation/html पर 400 पर खत्म होता है — पाथ को साइट के username रूट ने निगल लिया है।
  3. आर्काइव में ठीक वहीं एक छेद है जहाँ सनसेट है। Wayback Machine का पुराने changelog का आख़िरी सफल कैप्चर 24 मार्च 2024 है; नए वाले का पहला कैप्चर 23 अगस्त 2024 है। सनसेट की घोषणा 11 जून 2024 को हुई थी — यानी उसी पाँच महीने के गैप के अंदर।

इसमें से कुछ भी कोई साज़िश नहीं है; यह एक सामान्य CMS माइग्रेशन है। लेकिन इसका असर असली है, और यही वजह है कि यह लेख दोनों एंट्रियों को पूरा उद्धृत करता है: किसी deprecation का प्राथमिक रिकॉर्ड उस चीज़ से ज़्यादा टिकना चाहिए जिसे वह deprecate करता है, और यहाँ यह लगभग नहीं टिका।

असल में क्या टूटा

साइड प्रोजेक्ट्स नहीं। नीचे दी गई विफलताएँ सार्वजनिक इश्यू-ट्रैकर एंट्रियाँ हैं; टाइटल, तारीखें और स्थितियाँ GitHub और drupal.org APIs से ली गई हैं।

प्रोजेक्ट इश्यू खोला गया क्या कहता है
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” — बैकग्राउंड ऐप Source URIs पर बनाया गया था। अठारह महीने तक खुला रहा, 16 जुलाई 2024 को बंद हुआ।
sindresorhus/Actions #248 28 मई 2024 “Get Unsplash Image: 503 Error” — एक iOS/macOS Shortcuts एक्शन, सनसेट की घोषणा से दो सप्ताह पहले टूट गया।
Drupal — Gin Login #3324054 28 नवंबर 2022 “Unsplash has deprecated source.unsplash.com — this delays reCAPTCHA from loading, preventing users from logging in.”

आख़िरी पंक्ति को फिर से पढ़ें, क्योंकि यही वह है जिसे समझना ज़रूरी है। लॉगिन फॉर्म के बगल में एक सजावटी इमेज — पेज पर सबसे स्पष्ट रूप से गैर-ज़रूरी एसेट — एक ऑथेंटिकेशन outage में बदल गई, क्योंकि एक धीमा थर्ड-पार्टी रिक्वेस्ट उस CAPTCHA के आगे बैठा था जिसकी लॉगिन फॉर्म को ज़रूरत थी। किसी ने इसे ऐसे लिखने की योजना नहीं बनाई थी। यह उस क्रम से उभरा जिसमें ब्राउज़र चीज़ें लोड करता है।

आपके कोडिंग असिस्टेंट को यह मेमो नहीं मिला

यहीं वह हिस्सा है जो 2024 के outage को 2026 की समस्या बना देता है। source.unsplash.com को लगभग आठ साल तक डॉक्यूमेंट किया गया, ब्लॉग किया गया, पढ़ाया गया और कॉपी किया गया। वह सारा टेक्स्ट उन मॉडल्स के ट्रेनिंग डेटा में है जो अब हमारा स्टार्टर कोड लिखते हैं — और टेक्स्ट की कोई एक्सपायरी डेट नहीं होती। तीन आंकड़े:

माप30 अगस्त 2026 का मानकैसे लिया गया
source.unsplash.com वाली फ़ाइलें 3,344 GitHub कोड सर्च API, q=source.unsplash.com (केवल इंडेक्स किया गया सार्वजनिक कोड — यह न्यूनतम है, कुल नहीं)
100-फ़ाइल सैंपल में सनसेट के बाद बनाई गई रिपॉज़िटरी 77 में से 12 वही क्वेरी, 100 परिणाम, 77 रिपॉज़िटरी तक डिड्यूप्लिकेट, created_at की तुलना 11 जून 2024 से
…और उस सैंपल में पिछले 12 महीनों में पुश की गई रिपॉज़िटरी 77 में से 20 लाइव रिपॉज़िटरी, आर्काइव नहीं — जिसमें elastic/kibana भी शामिल है, जिसकी डेमो फ़ाइल अभी भी imageUrl: 'https://source.unsplash.com/64x64/?dingo' पढ़ती है
unsplash-source-es6 के मासिक डाउनलोड 23 npm रजिस्ट्री API — एक मृत सेवा के लिए एक रैपर, आख़िरी बार 2022 में प्रकाशित, अभी भी इंस्टॉल किया जा रहा है
इसका ज़िक्र करने वाली Stack Overflow पोस्ट 1,459 Stack Exchange API, /search/excerpts कुल

सबसे सीधा प्रमाण एप्लिकेशन कोड में बिल्कुल नहीं है — यह प्रॉम्प्ट्स में है। उस सर्च का शीर्ष परिणाम GPT सिस्टम प्रॉम्प्ट्स की एक लाइब्रेरी है जिसमें यह पंक्ति है “please use unsplash API( https://source.unsplash.com/1280x720/?<PUT YOUR QUERY HERE>”। वह निर्देश आज भी नए असिस्टेंट्स में कॉपी किया जा रहा है। मॉडल URL को वेरिफ़ाई नहीं करता; उसे इसे इस्तेमाल करने के लिए कहा गया था, और उसने जो भी उदाहरण देखा, वह इससे सहमत था।

तो जनरेट किए गए कोड की विफलता के दो स्वतंत्र कारण हैं, और एक को ठीक करने से दूसरा ठीक नहीं होता: पुराना ट्रेनिंग डेटा, और उसके ऊपर इंसानों द्वारा लिखे गए पुराने निर्देश। दोनों ही स्थितियों में, लक्षण उन इमेजेज़ का एक ही परिवार है जो कभी लोड नहीं होतीं:

मृत-इमेज पैटर्न जिन्हें grep करना ज़रूरी है
source.unsplash.com/random/1200x800   # mid-2024 से 503 — कभी वापस नहीं आता
images.unsplash.com/photo-…           # असली CDN, पर याद रखे गए IDs मौजूद न हों तो
via.placeholder.com/400               # स्लेटी आयत, प्रोडक्शन में शिप हो गया
placehold.co/800x600                  # स्लेटी आयत, जान-बूझकर
picsum.photos/800/600                 # एक असली फोटो, आपके पेज से असंबंधित
/placeholder.png                      # एक फ़ाइल जो कभी repo में जोड़ी ही नहीं गई

उस सूची की दूसरी पंक्ति पर एक फुटनोट: यह लिखते समय, via.placeholder.com ने हमारे टेस्ट नेटवर्क से भी TLS handshake पूरा नहीं किया, और सामान्य HTTP पर 403 से जवाब दिया। इस पर भरोसा करने से पहले अपने ही नेटवर्क से इसे जाँच लें — ये टूल्स जिस फ़ॉलबैक की ओर जाते हैं, उसकी अपनी outage कहानी भी हो सकती है।

इनमें से केवल पहला ही टूटा हुआ है। बाकी एक ज़्यादा सूक्ष्म तरीके से बदतर हैं: वे लोड होते हैं, लेआउट पूरा दिखता है, और किसी को पता ही नहीं चलता कि पेज पर कोई खास चीज़ नहीं दिखाई गई है। और यह सब इमेजेज़ के लिए ही खास नहीं है — यह समस्या का सामान्य स्वरूप है। किसी मॉडल के पास वेब की जो तस्वीर है, वह एक स्नैपशॉट है, और शटर बंद होने के बाद भी एंडपॉइंट्स, CLI फ़्लैग्स, पैकेज नाम और फ्री टियर बदलते रहते हैं।

माइग्रेशन टेबल

ठीक तीन गंतव्य हैं, और इन्हें ईमानदारी से पेश करने का तरीका यह है कि आप क्या छोड़ रहे हैं। पहले कॉलम चुनें, फिर अपनी पंक्ति पढ़ें।

पुराना Source URL A. फिक्स्ड CDN URLबिना key · बिना रैंडमनेस B. Unsplash APIkey · सर्वर-साइड कॉल C. आपका अपना प्रॉक्सीkey छिपी हुई · रैंडमनेस वापस
/random images.unsplash.com/photo-… — आपकी चुनी हुई एक फोटो GET /photos/random /?w=1600
/random/1600x900 …?w=1600&h=900&fit=crop /photos/random + लौटाए गए URL पर Imgix पैरामीटर /?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 वही है जिसे ज़्यादातर लोग वास्तव में चाहते हैं। अगर इमेज सजावटी थी — कोई हीरो, लॉगिन साइड पैनल, कार्ड बैकग्राउंड — तो आपको कभी हर रिक्वेस्ट पर अलग फोटो की ज़रूरत ही नहीं थी। एक चुनें, CDN URL को रखें, और पेज का किसी रैंडम चीज़ पर निर्भर रहना बंद हो जाता है:

एक फिक्स्ड, resizable Unsplash URL — बिना key, बिना API कॉल
<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 आधिकारिक रास्ता है, और यह कॉल को सर्वर-साइड ले जाता है, क्योंकि फ्रंट-एंड JavaScript में Client-ID एक प्रकाशित क्रेडेंशियल है। दो नियम ध्यान रखें जो लोगों को उलझा देते हैं: collections/topics को उसी रिक्वेस्ट में query के साथ नहीं मिलाया जा सकता, और count (अधिकतम 30) रिस्पॉन्स के आकार को एक ऐरे में बदल देता है, भले ही वह 1 ही क्यों न हो।

/random का आधिकारिक विकल्प
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 को फिर से बनाएँ, करीब चालीस लाइनों में

अगर आपने जो खोया वह असल में व्यवहार ही था — एक बिना-key वाला URL जो हर बार अलग फोटो लौटाता है, सीधे <img> टैग से, किसी CMS फ़ील्ड में, या किसी स्टैटिक साइट में जहाँ कोई सर्वर नहीं है — तो आपको वह एंडपॉइंट खुद चलाना होगा। यह API के आगे एक छोटा वर्कर है, और तीन चीज़ें जो इसे प्रोडक्शन के सामने ज़िंदा रखती हैं वे हैं कैश, referrer चेक, और बाकी क्वेरी स्ट्रिंग को CDN तक पास करना।

worker.js — /photos/random के ऊपर एक बिना-key वाला Source-जैसा एंडपॉइंट
// Cloudflare Workers. कहीं और (Deno Deploy, Val Town…) स्वरूप वही है,
// पर caches.default की जगह caches.open() से एक नामित कैश खोलें।
// 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. सिर्फ़ आपके अपने पेज इसे embed कर सकें — खुले इंटरनेट पर एक सार्वजनिक
    //    रैंडम-फोटो एंडपॉइंट किसी और का rate limit जलाने का ज़रिया है।
    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 आमतौर पर घंटे का कोटा है, ख़राब key नहीं — TTL बढ़ाएँ, घबराएँ नहीं।
    if (!r.ok) return new Response("Upstream " + r.status, { status: 502 });
    const photo = await r.json();

    // 4. इमेज URL फिर से बनाएँ: ixid रखें, कॉलर के sizing पैरामीटर जोड़ें।
    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) आपको बैंडविड्थ की ज़िम्मेदारी से बचाता है और Unsplash के CDN पर व्यू को गिना हुआ रखता है, जो कि गाइडलाइंस की माँग है। और Referer चेक जानबूझकर तब उदार है जब हेडर मौजूद न हो — कई वैध क्लाइंट्स इसे हटा देते हैं — फिर भी यह उस स्पष्ट स्थिति को रोकता है जिसमें आपका एंडपॉइंट किसी और की मुफ़्त इमेज API बन जाए।

API इस्तेमाल करते ही जो नियम आप विरासत में पाते हैं

Source के कोई नियम नहीं थे क्योंकि इसका कोई अकाउंट नहीं था। API के पास पाँच ऐसे नियम हैं जो यह बदल देते हैं कि आप इसे कैसे आर्किटेक्ट करें, सभी वर्तमान डॉक्यूमेंटेशन से:

  • Rate limit प्रति घंटे हैं, और शुरुआत में छोटे। डेमो मोड में 50 requests/hour; आपके एप्लिकेशन को प्रोडक्शन के लिए स्वीकृत हो जाने के बाद 1,000/hour। सिर्फ़ api.unsplash.com पर की गई कॉल्स गिनी जाती हैं — images.unsplash.com पर इमेज रिक्वेस्ट नहीं गिनी जातीं। हर रिस्पॉन्स पर X-Ratelimit-Remaining पढ़ें।
  • Hotlinking अनिवार्य है, सिर्फ़ अनुमति प्राप्त नहीं। Unsplash की माँग है कि API द्वारा लौटाए गए इमेज URLs सीधे embed किए जाएँ, ताकि फोटो व्यूज़ का श्रेय फ़ोटोग्राफ़र को दिया जा सके। फ़ाइल को अपने ही CDN पर मिरर करना ही एकमात्र ऑप्टिमाइज़ेशन है जो आप नहीं कर सकते।
  • ixid पैरामीटर रखें। लौटाए गए URL का resize और crop करना अपेक्षित है; उस पैरामीटर को हटाना नहीं जो आपके एप्लिकेशन की पहचान करता है।
  • Attribution और download tracking इस समझौते का हिस्सा हैं — फ़ोटोग्राफ़र और Unsplash दोनों को क्रेडिट मिलता है, और जब कोई यूज़र फ़ाइल लेता है तब एक “download” फोटो के download एंडपॉइंट के ज़रिए रिपोर्ट किया जाता है, जो एक ऐसा इवेंट है जिसे आपको खुद फायर करना पड़ता है।
  • वितरित प्रोडक्ट्स को dynamic client registration चाहिए। अगर आप कोई प्लगइन, थीम या self-hosted CMS शिप करते हैं, तो एक साझा key एक साथ पॉलिसी उल्लंघन भी है और failure का एक ही बिंदु भी; API के पास ठीक इसी स्थिति के लिए एक registration फ़्लो है।

यह ईमानदार होने का मौका है कि दायरा क्या है: अगर आप वैसे भी एक API और एक key से जुड़ रहे हैं, तो कौन-सी इमेज API चुनें, यह विकल्प अचानक खुल जाता है, और क्लाइंट लिखने से पहले इस पर पाँच मिनट देना उचित है। हमने मुफ़्त वालों की तुलना की — कोटा, नियम, सर्च व्यवहार और रिस्पॉन्स के स्वरूप — इसमें फ्री स्टॉक फोटो API तुलना।

अगर आपको सिर्फ़ प्लेसहोल्डर चाहिए था, तो साफ़ कहें

Source के इस्तेमाल का एक बड़ा हिस्सा Unsplash के बारे में कभी था ही नहीं। यह “जब तक मैं लेआउट बना रहा हूँ, यहाँ कोई इमेज-जैसी चीज़ रख दो” वाली बात थी। इसके लिए, बिना-key वाली सेवाएँ अभी भी मौजूद हैं और सही जवाब हैं:

सेवाKey?क्या मिलता हैकहाँ रुक जाती है
Lorem Picsum No असली फोटोग्राफ़्स: picsum.photos/800/600, /id/237/… या /seed/xxx/… से एक स्थिर वाली, साथ ही ?grayscale और ?blur=1..10। इसका /v2/list एंडपॉइंट हर फोटो के Unsplash पेज और लेखक को क्रेडिट देता है। कोई सब्जेक्ट टारगेटिंग नहीं। फोटो आपके पेज से संबंधित नहीं होगी।
placehold.co No किसी भी साइज़ में लेबल्ड आयत — ईमानदार वायरफ़्रेम फिलर। यह एक स्लेटी बॉक्स है, और किसी क्लाइंट के साथ शेयर किए गए स्क्रीनशॉट में ऐसा ही दिखता है।
Openverse No एक सार्वजनिक API के साथ खुले लाइसेंस वाला कैटलॉग, WordPress.org द्वारा संचालित। कीवर्ड मैचिंग, और लाइसेंस हर आइटम पर अलग होते हैं — आपको उन्हें पढ़ना होगा।

जो अंतर मायने रखता है: एक प्लेसहोल्डर परिभाषा से ही अस्थायी होता है। अगर वह इमेज प्रोडक्शन तक जीवित रहती है, तो वह अब प्लेसहोल्डर नहीं है — यह एक ऐसा इलस्ट्रेशन है जिसे किसी ने नहीं चुना, और पाठक इसे पहचान सकता है।

तीन की जगह एक key

यहाँ माइग्रेशन का वह हिस्सा है जिसकी कोई योजना नहीं बनाता: Source छोड़ने वाले लोग शायद ही एक API पर जाकर रुकते हैं। किसी पेज को एक हीरो, दो सेक्शन इमेज और कार्ड ग्रिड के लिए कुछ चाहिए होता है, और ईमानदार जवाब आमतौर पर Unsplash के साथ-साथ Pexels और Pixabay होता है — तीन रजिस्ट्रेशन, तीन auth स्कीम, तीन JSON स्वरूप, तीन पेजिनेशन मॉडल और तीन तरह के attribution नियम, सब वही <img> टैग भरने के लिए। यही इंटीग्रेशन का असली बिल है जो एक बिना-key वाला URL के चले जाने पर आता है, और यह उस outage के हफ़्तों बाद पहुँचता है जिसने इसे जन्म दिया।

इसे एक ही इंटीग्रेशन में समेटना ही वह वजह है जिसके लिए हमने Pexafy बनाया: एक ही स्कीमा में 9 फ्री-लाइसेंस लाइब्रेरीज़ पर एक ही key, वाक्य-स्तर की सिमैंटिक सर्च के साथ — ताकि “a cracked phone screen on a wooden desk, shot from above” जैसा पूरा विवरण कुछ न मिलने की बजाय रैंक किए गए परिणाम लौटाए। दो सीमाएँ, साफ़ शब्दों में बताई गई हैं, क्योंकि यह पूरा लेख दोबारा हैरान न होने के बारे में है: इसे एक key चाहिए, इसलिए यह Source जो था उसे वापस नहीं लाता — यह ऊपर बताए गए आधिकारिक Unsplash API के ही वर्ग में आता है; और यह फ्री-लाइसेंस फ़ोटोग्राफी रखता है, संपादकीय या ब्रांड इमेजरी नहीं।

जो हिस्सा वास्तव में नया है वह ऊपर बताए असिस्टेंट्स के लिए है: mcp.pexafy.com/mcp पर एक MCP सर्वर का मतलब है कि जो मॉडल अन्यथा याददाश्त से एक इमेज URL पढ़ता, वह अब एक असली कैटलॉग सर्च कर सकता है और एक ऐसी फोटो लौटा सकता है जो वाकई मौजूद है, उसकी क्रेडिट लाइन के साथ। मशीन-लिखित मृत URLs का इससे बेहतर जवाब किसी भी lint नियम के पास नहीं है, और इसका तर्क AI एजेंट्स के लिए इमेज सर्च इन्फ्रास्ट्रक्चर में लिखा गया है।

दस मिनट में अपनी संपत्ति ऑडिट करें

आप जिस भी चीज़ पर माइग्रेट करें, यह हिस्सा पहले करें — जिन URLs को आपने ढूँढा ही नहीं, उन्हें आप ठीक नहीं कर सकते। Source सिर्फ़ आज का उदाहरण है; वही तीन कदम हर बाहरी एसेट पर लागू होते हैं जिसे आप embed करते हैं।

हर मृत रेफ़रेंस ढूँढें, फिर उन्हें दूर रखें
# 1. repo में सब कुछ, जिसमें docs, tests, fixtures और READMEs शामिल हैं।
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. बनी हुई साइट जो कुछ भी वाकई रिक्वेस्ट करती है: उसे क्रॉल करें और विफलताएँ सूचीबद्ध करें।
#    फ़ाइल एक्सटेंशन नहीं, attribute मैच करें — इमेज URLs शायद ही .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   ← जो आप ढूँढ रहे हैं

फिर एक बार तय कर लें कि बाहरी इमेजेज़ आपको कितनी कीमत चुकाने की अनुमति दे सकती हैं। चार नियम जो अगले शटडाउन से बचे रहते हैं, चाहे उसे कोई भी वजह दे:

  1. बिल्ड टाइम पर fetch करें, रिक्वेस्ट टाइम पर नहीं। बिल्ड के दौरान resolve हुई इमेज CI में विफल होती है, किसी डेवलपर के सामने, न कि रात 3 बजे किसी यूज़र के सामने।
  2. कभी किसी सजावटी एसेट को क्रिटिकल पाथ को ब्लॉक न करने दें। लॉगिन फॉर्म के ऊपर कोई बाहरी चीज़ preload न करें; हर थर्ड-पार्टी <img> को एक onerror फ़ॉलबैक और स्पष्ट width/height दें ताकि विफलता की कीमत सिर्फ़ एक खाली बॉक्स हो, न कि कोई लेआउट शिफ्ट या रुकी हुई स्क्रिप्ट।
  3. चेक को CI में जोड़ें। ऊपर वाला स्टेप 3, आपके बिल्ड आउटपुट पर चलाया जाए, तो “किसी को आखिर में पता चला” को एक लाल बिल्ड में बदल देता है। यही एकमात्र स्टेप है जो पुनरावृत्ति को रोकता है।
  4. अपनी बाहरी निर्भरताओं का बजट किसी और की तरह ही तय करें। लिख लें कि आपके पेज किन होस्ट्स पर निर्भर रह सकते हैं और हर एक के डाउन होने पर क्या होता है। जिस URL के लिए आपको रजिस्टर नहीं करना पड़ा, वह भी एक निर्भरता ही है — Source ने साबित किया कि यह बस ऐसी निर्भरता है जिसका कोई मालिक नहीं है।

संदर्भ और फुटनोट्स

1 इस लेख में हर स्टेटस कोड, गिनती और उद्धृत पंक्ति 30 अगस्त 2026 को उसके प्राथमिक स्रोत से ली गई थी। HTTP स्टेटस कोड हर URL पैटर्न के विरुद्ध curl से लिए गए; सभी ने server: Heroku के साथ 503 लौटाया और बॉडी में herokucdn.com/error-pages/application-error.html embedded था। DNS resolution उसी दिन कन्फ़र्म किया गया (एक herokudns.com होस्ट का CNAME)।

2 दोनों changelog एंट्रियाँ unsplash.com/documentation/changelog से शब्दशः उद्धृत हैं। Deprecation-पॉलिसी का शब्दांकन (3 सप्ताह की सूचना, Warning हेडर, और गैर-सार्वजनिक रूप से दस्तावेज़ीकृत एंडपॉइंट्स के लिए छूट) उसी दिन unsplash.com/documentation से लिया गया।

3 TLS विफलता openssl s_client -connect changelog.unsplash.com:443 से दोहराई गई (tlsv1 alert internal error)। रीडायरेक्ट चेन curl -L से फॉलो की गई। आर्काइव गैप Wayback CDX API से लिया गया: changelog.unsplash.com का आख़िरी 200 कैप्चर 20240324 को, unsplash.com/documentation/changelog का पहला 20240823 को।

4 इश्यू टाइटल, बनाने और बंद होने की तारीखें GitHub REST API (mui/material-ui#42736, nextcloud/unsplash#115, sindresorhus/Actions#248) और drupal.org JSON API से gin_login इश्यू 3324054 के लिए पढ़ी गईं, जिसकी बॉडी नवंबर 2022 में “I get always a Heroku application error” रिपोर्ट करती है।

5 आंकड़े: GitHub कोड सर्च API (3,344 फ़ाइलें; 100-परिणाम का सैंपल 77 रिपॉज़िटरी तक डिड्यूप्लिकेट, जिनमें से 12 11 जून 2024 के बाद बनाई गईं और 20 को पिछले 12 महीनों में पुश किया गया था); npm रजिस्ट्री डाउनलोड API (unsplash-source-es6, पिछले 30 दिनों में 23 डाउनलोड); Stack Exchange /search/excerpts (1,459 पोस्ट)। कोड सर्च सिर्फ़ इंडेक्स किए गए सार्वजनिक रिपॉज़िटरी को कवर करता है, इसलिए हर आंकड़ा एक न्यूनतम है।

अक्सर पूछे जाने वाले प्रश्न

क्या source.unsplash.com डाउन है, या इसे स्थायी रूप से बंद कर दिया गया है?
स्थायी रूप से। Unsplash ने 11 जून 2024 को इसके बंद होने की घोषणा की — “हम पहले सर्च फीचर को बंद करके इसे धीरे-धीरे समेटेंगे, और आने वाले हफ्तों में एप्लिकेशन को पूरी तरह बंद कर देंगे” — यह 25 नवंबर 2021 को सेवा को डिप्रिकेट करने के बाद हुआ। हर पैटर्न (/random, /1600x900/?query, /collection/…, /daily) अब HTTP 503 रिटर्न करता है, साथ में Heroku का जेनेरिक Application Error पेज। होस्टनेम अभी भी रिज़ॉल्व होता है, इसलिए यह फेलियर नेटवर्क एरर की बजाय टूटी हुई इमेज के रूप में दिखता है।
source.unsplash.com/random का सीधा विकल्प क्या है?
बिना-की वाला कोई ड्रॉप-इन विकल्प नहीं है, और यह बात जल्दी स्वीकार कर लेना बेहतर है। तीन विकल्प मौजूद हैं। एक फिक्स्ड CDN URL — images.unsplash.com/photo-…?w=1600&h=900&fit=crop — को किसी की की जरूरत नहीं, लेकिन यह हमेशा वही एक फोटो रिटर्न करता है, जो ज़्यादातर डेकोरेटिव उपयोगों के लिए वास्तव में काफी था। आधिकारिक API, GET https://api.unsplash.com/photos/random, जिसे Authorization: Client-ID हेडर के साथ कॉल किया जाता है, रैंडमनेस वापस लाता है लेकिन इसे सर्वर-साइड पर ही कॉल किया जाना चाहिए। आपकी खुद की एक छोटी प्रॉक्सी इस एंडपॉइंट के आगे लगाना ही एकमात्र तरीका है जो आपको एक बिना-की वाला URL वापस देता है जिसे आप सीधे <img> टैग में डाल सकते हैं।
2026 में भी AI कोडिंग टूल्स source.unsplash.com URLs क्यों जनरेट करते हैं?
क्योंकि यह URL लगभग आठ साल तक दस्तावेज़ीकृत, सिखाया और कॉपी किया जाता रहा, और जब कोई सेवा बंद होती है तो ट्रेनिंग कॉर्पस अपने आप एक्सपायर नहीं हो जाता। 30 अगस्त 2026 को मापा गया: GitHub कोड सर्च अब भी 3,344 फाइलें रिटर्न करता है जिनमें यह मौजूद है, और 100-फाइल के सैंपल में 77 में से 12 रिपॉजिटरी शटडाउन के बाद बनाई गई थीं। इंसानों द्वारा लिखी गई प्रॉम्प्ट लाइब्रेरियां भी यही निर्देश दोहराती हैं — एक बड़े पैमाने पर कॉपी किया गया GPT प्रॉम्प्ट अब भी मॉडल को “unsplash API( https://source.unsplash.com/1280x720/?… ) का उपयोग करें” कहता है। मॉडल द्वारा लिखे गए किसी भी इमेज URL को असत्यापित मानें और CI में स्टेटस कोड चेक करें।
क्या मैं अब भी बिना API key के कोई रैंडम Unsplash फोटो पा सकता हूँ?
Unsplash से सीधे नहीं — रैंडम सिलेक्शन अब /photos/random के पीछे है, जिसके लिए Client-ID ज़रूरी है। आपके पास दो बिना-की वाले रास्ते हैं: एक प्रॉक्सी जिसे आप खुद होस्ट करते हैं, जहां की सर्वर-साइड पर रहती है और पब्लिक URL पुराने जैसा ही दिखता है, या फिर Lorem Picsum (picsum.photos/800/600) जैसी थर्ड-पार्टी प्लेसहोल्डर सेवा, जो बिना की के असली फोटोग्राफ्स तो देती है लेकिन विषय-लक्षित करने की कोई सुविधा नहीं देती।
क्या Unsplash API इमेजेस को डाउनलोड करके सेल्फ-होस्ट करने की अनुमति देता है?
नहीं। ज़्यादातर APIs के विपरीत, Unsplash हॉटलिंकिंग को अनिवार्य बनाता है: API द्वारा दिए गए इमेज URLs को सीधे एम्बेड किया जाना चाहिए, ताकि फोटो व्यूज़ फोटोग्राफर के लिए गिने जाएं। इसके साथ तीन ज़िम्मेदारियां आती हैं — URL को रीसाइज़ या क्रॉप करते समय ixid पैरामीटर बनाए रखें, फोटोग्राफर और Unsplash को क्रेडिट दें, और जब कोई यूज़र फाइल लेता है तो फोटो के डाउनलोड एंडपॉइंट को फायर करें। फाइलों को अपने खुद के CDN पर मिरर करना एक ऐसा ऑप्टिमाइज़ेशन है जो आपको करने की आज़ादी नहीं है।
2021 का डिप्रिकेशन नोटिस मौजूदा यूज़र्स की सुरक्षा क्यों नहीं कर पाया?
क्योंकि नोटिस और पॉलिसी एक ही चीज़ को कवर नहीं करते थे। 25 नवंबर 2021 की चेंजलॉग एंट्री में वादा किया गया था कि “मौजूदा उपयोग काम करते रहेंगे”, और कोई अंतिम तारीख नहीं दी गई थी। Unsplash की प्रकाशित डिप्रिकेशन पॉलिसी — कम से कम तीन हफ्ते का नोटिस और एक Warning हेडर — केवल सार्वजनिक रूप से दस्तावेज़ीकृत फील्ड्स और एंडपॉइंट्स पर लागू होती है, और उसी पैराग्राफ में यह भी लिखा है कि जो कुछ दस्तावेज़ीकृत नहीं है वह बिना किसी चेतावनी के बदल सकता है। Source कभी भी API का दस्तावेज़ीकृत एंडपॉइंट नहीं था, इसलिए यह उस पॉलिसी के दायरे से बाहर रहा जो इसकी रक्षा कर सकती थी।
मैं अपने प्रोजेक्ट में हर मृत source.unsplash.com URL कैसे ढूंढूं?
तीन चरण, दस मिनट। रिपॉजिटरी को grep करें, जिसमें docs, tests, fixtures और README भी शामिल हों — grep -rn "source.unsplash.com" . — क्योंकि ये URLs सैंपल कोड में सबसे लंबे समय तक टिके रहते हैं। डेटाबेस को क्वेरी करें, क्योंकि CMS आर्टिकल बॉडीज़ वे जगहें हैं जहां ये छुपे रहते हैं (WHERE body LIKE '%source.unsplash.com%')। फिर अपने बिल्ट आउटपुट को क्रॉल करें: हर इमेज URL निकालें और हर एक को रिक्वेस्ट करें, जो भी 200 नहीं है उसे सूचीबद्ध करें। इस आखिरी चरण को CI में जोड़ दें ताकि कोई मृत थर्ड-पार्टी एसेट पूरे पेज की बजाय बिल्ड को फेल करे।

कीवर्ड खोजना बंद करें। बस वर्णन करें कि आपका मतलब क्या है।

किसी भी भाषा में, 100 ms से कम में, अर्थ के आधार पर 9M+ मुफ़्त-उपयोग छवियों की खोज करें।