I often want to add visually interesting elements to my projects and struggle with content. Let’s say you have a subpage that shows all the posts/any other information related to a city. It would be great to have a photo of said city in the header, wouldn’t it?
You may think that the way to go is to generate something with AI. It may work, but there are many issues with this approach.
There are great free stock photo sites like Pexels or Unsplash. But how to find the right picture?
I stumbled upon this problem while working on one of my side projects. It turns out Unsplash has a great API. In Python, we need to call it manually but there are client packages for JS, Ruby, PHP, mobile, etc.
The API basically allows you to find photos matching your search query. A few caveats:
Make sure you use direct links from Unsplash. Downloading and re-hosting images is not allowed.
You must attribute Unsplash and the author.
The API is rate limited to 50 requests per hour for unverified apps, 5k after approval and more if you need it.
More on usage guidelines: Unsplash.
Getting started (in-depth guide):
Sign up for an account: https://unsplash.com/oauth/applications
Go to your apps: https://unsplash.com/oauth/applications
Create a “New application.”
Go to your app and save Access key; we’ll need it in the following steps
Have a look at this sample function; you can adapt it to your needs.
import requests
import os
# Load Unsplash API key from environment variables
UNSPLASH_ACCESS_KEY = os.getenv('UNSPLASH_ACCESS_KEY')
def fetch_image_info(query):
url = "<https://api.unsplash.com/search/photos>"
params = {
"query": query,
"client_id": UNSPLASH_ACCESS_KEY,
"per_page": 1,
"orientation": "landscape",
}
response = requests.get(url, params=params)
if response.status_code == 200:
data = response.json()
if data['results']:
return data['results'][0]
elif response.status_code == 403:
raise ConnectionError("Rate limited or not authorized")
return None
When you call this function for a “New York” query, you should receive an object like that:
{
"id": "string",
"slug": "string",
"created_at": "string",
"width": "integer",
"height": "integer",
"color": "string",
"blur_hash": "string",
"alt_description": "string",
"breadcrumbs": "array",
"urls": "object",
"links": "object",
"likes": "integer",
"user": "object",
"tags": "array",
"...": "..."
}
You should pay attention to three of them really.
First, urls
- this is what you will use in your app.
"urls": {
"raw": "<https://images.unsplash.com/photo-1496442226666-8d4d0e62e6e9?ixid=M3w2MjA1MzR8MHwxfHNlYXJjaHwxfHxOZXclMjBZb3JrfGVufDB8MHx8fDE3MjA5MDAxMTd8MA&ixlib=rb-4.0.3>",
"full": "<https://images.unsplash.com/photo-1496442226666-8d4d0e62e6e9?crop=entropy&cs=srgb&fm=jpg&ixid=M3w2MjA1MzR8MHwxfHNlYXJjaHwxfHxOZXclMjBZb3JrfGVufDB8MHx8fDE3MjA5MDAxMTd8MA&ixlib=rb-4.0.3&q=85>",
"regular": "<https://images.unsplash.com/photo-1496442226666-8d4d0e62e6e9?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w2MjA1MzR8MHwxfHNlYXJjaHwxfHxOZXclMjBZb3JrfGVufDB8MHx8fDE3MjA5MDAxMTd8MA&ixlib=rb-4.0.3&q=80&w=1080>",
"small": "<https://images.unsplash.com/photo-1496442226666-8d4d0e62e6e9?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w2MjA1MzR8MHwxfHNlYXJjaHwxfHxOZXclMjBZb3JrfGVufDB8MHx8fDE3MjA5MDAxMTd8MA&ixlib=rb-4.0.3&q=80&w=400>",
"thumb": "<https://images.unsplash.com/photo-1496442226666-8d4d0e62e6e9?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w2MjA1MzR8MHwxfHNlYXJjaHwxfHxOZXclMjBZb3JrfGVufDB8MHx8fDE3MjA5MDAxMTd8MA&ixlib=rb-4.0.3&q=80&w=200>",
"small_s3": "<https://s3.us-west-2.amazonaws.com/images.unsplash.com/small/photo-1496442226666-8d4d0e62e6e9>",
},
Second, user
- you will use this info for proper attribution, namely:
user.name
: Author name
user.links.html
: Link to their profile, you must use. Make sure to append utm_source=your_app_name&utm_medium=referral
to it, per guidelines.
Third, alt_description
, make sure to add it to your final IMG tags for accessibility and SEO.
This piece of code is really everything you need to get going. With one caveat.
When you’re in initial demo mode, you will only have 50 requests per hour. When trying to fetch more images, hitting rate limit is a given. What to do?
Simply wait for a bit if the function above throws ConnectionError. I wait for around 70 seconds.
Also mind that if no results are found, you will receive None. In this case, I am using a simplified query (country instead of city).
Once the website is online, you can request higher quota in the dashboard.
We've covered how to use Python and the Unsplash API to automatically fetch photos for your apps and websites.
I hope you’ll build something cool with it. Send your projects my way in the comments or on Twitter.
Subscribe to my profile by filling in your email address on the left, and be up-to-date with my articles! I will soon be releasing a crazy interesting project that uses this solution!
Don't forget to follow me on Twitter @horosin, and subscribe to my blog’s newsletter for more tips and insights!