Finding high-quality, royalty-free images for every blog post is time-consuming. Manually searching Unsplash, downloading images, uploading to WordPress, and adding attribution takes 5-10 minutes per post. For content-heavy sites publishing daily, that’s hours of wasted effort every week.
- Why Automate Images with Unsplash?
- Prerequisites
- Getting Unsplash API Access
- Understanding Unsplash API
- Fetching Images with curl
- Downloading Images
- Importing to WordPress Media Library
- Setting Featured Images
- Handling Attribution
- Complete Automation Script
- Advanced Features
- Error Handling
- Rate Limiting
- Integration with Publishing Pipeline
- Troubleshooting
- Next Steps
- Conclusion
What if you could automatically fetch relevant images from Unsplash and set them as featured images—all from the command line?
In this tutorial, you’ll learn to integrate the Unsplash API with WordPress using WP-CLI and Bash. You’ll build a complete automation system that searches for images, downloads them, imports to WordPress media library, sets featured images, and handles proper attribution automatically.
This is a key component of the automated blog publishing pipeline you’ll build in WPCLI Mastery.
Why Automate Images with Unsplash?
The Manual Image Problem
Typical workflow:
- Search Unsplash for relevant image (2 min)
- Download image (30 sec)
- Upload to WordPress (1 min)
- Set as featured image (30 sec)
- Add attribution in caption/alt text (1 min)
Total: ~5 minutes per post
For 20 posts/month = 100 minutes wasted
Automated Solution
With WP-CLI + Unsplash API:
# One command, 5 seconds
wp unsplash set-featured 123 --query="technology"
Result:
- Image downloaded
- Imported to media library
- Set as featured image
- Attribution added
- Alt text optimized
Unsplash Benefits
High Quality: Professional photography, all free Huge Library: Over 3 million images Legal Safety: Completely free for commercial use Developer-Friendly: Well-documented API SEO Value: Proper attribution builds credibility
According to Unsplash, images are downloaded over 10 billion times per year. It’s the go-to source for professional content creators.
Prerequisites
Before integrating Unsplash API, ensure you have:
Required Software
- WP-CLI installed – Installation guide
- curl – For API requests
- jq – JSON parsing tool
- Bash – Shell scripting knowledge
Install missing tools:
# Ubuntu/Debian
sudo apt-get install curl jq
# macOS
brew install curl jq
WordPress Requirements
- WordPress site with WP-CLI access
- Write permissions for uploads directory
- Basic understanding of WordPress media library
Bash Knowledge
Helpful background:
- Bash functions for WordPress
- API requests with curl
- JSON parsing basics
Getting Unsplash API Access
Step 1: Create Unsplash Account
- Visit Unsplash.com
- Sign up for free account
- Verify your email
Step 2: Register Your Application
- Go to Unsplash Developers
- Click “Register as a Developer”
- Accept the API terms
- Click “New Application”
Step 3: Create API Application
Fill in application details:
- Application name: “WordPress Blog Automation”
- Description: “Automated featured image fetching for WordPress blog”
- Callback URLs: (not needed for this use case)
Important: Accept the API Guidelines
Step 4: Get API Keys
After creating your app, you’ll receive:
- Access Key: Public key for API requests (Demo: Limited to 50 requests/hour)
- Secret Key: Keep private (not needed for basic usage)
Demo vs Production:
- Demo: 50 requests/hour (good for testing)
- Production: 5,000 requests/hour (requires app approval by Unsplash)
For most blogs, demo limits are sufficient. Production approval takes 1-2 business days.
Step 5: Store API Key Securely
Never hardcode API keys in scripts.
Store in environment variable:
# Add to ~/.bashrc or ~/.bash_profile
export UNSPLASH_ACCESS_KEY="your_access_key_here"
# Reload
source ~/.bashrc
Or use a config file:
# Create config file
nano ~/.unsplash-config
# Add key
UNSPLASH_ACCESS_KEY=your_access_key_here
# Secure it
chmod 600 ~/.unsplash-config
Understanding Unsplash API
API Endpoints
Search Photos:
GET https://api.unsplash.com/search/photos
Get Random Photo:
GET https://api.unsplash.com/photos/random
Get Specific Photo:
GET https://api.unsplash.com/photos/{id}
Basic API Request
curl -H "Authorization: Client-ID YOUR_ACCESS_KEY" \
"https://api.unsplash.com/photos/random?query=nature"
Response Format
Unsplash returns JSON:
{
"id": "abc123",
"urls": {
"raw": "https://images.unsplash.com/photo-...",
"full": "https://images.unsplash.com/photo-...",
"regular": "https://images.unsplash.com/photo-...",
"small": "https://images.unsplash.com/photo-..."
},
"user": {
"name": "John Doe",
"username": "johndoe",
"links": {
"html": "https://unsplash.com/@johndoe"
}
},
"description": "Beautiful sunset over mountains",
"alt_description": "orange sunset"
}
Key fields:
urls.regular: Best for WordPress featured images (1080px wide)user.name: For attributionuser.links.html: Link to photographer’s profilealt_description: Good for alt text
Read full docs: Unsplash API Documentation
Fetching Images with curl
Search for Images
#!/bin/bash
UNSPLASH_KEY="your_access_key"
QUERY="technology"
# Search for images
response=$(curl -s -H "Authorization: Client-ID ${UNSPLASH_KEY}" \
"https://api.unsplash.com/search/photos?query=${QUERY}&per_page=1")
# Parse response with jq
image_url=$(echo "$response" | jq -r '.results[0].urls.regular')
photo_id=$(echo "$response" | jq -r '.results[0].id')
photographer=$(echo "$response" | jq -r '.results[0].user.name')
photographer_url=$(echo "$response" | jq -r '.results[0].user.links.html')
alt_text=$(echo "$response" | jq -r '.results[0].alt_description')
echo "Image URL: ${image_url}"
echo "Photographer: ${photographer}"
echo "Alt Text: ${alt_text}"
Get Random Image
get_random_image() {
local query=$1
local orientation=${2:-landscape} # landscape, portrait, squarish
local response=$(curl -s -H "Authorization: Client-ID ${UNSPLASH_KEY}" \
"https://api.unsplash.com/photos/random?query=${query}&orientation=${orientation}")
echo "$response"
}
# Usage
response=$(get_random_image "coding" "landscape")
image_url=$(echo "$response" | jq -r '.urls.regular')
Search Parameters
Common parameters:
# Search with pagination
?query=nature&page=2&per_page=10
# Filter by orientation
?query=laptop&orientation=landscape
# Filter by color
?query=sunset&color=orange
# Combine filters
?query=workspace&orientation=landscape&color=black_and_white
Orientation options:
landscape– Horizontal (best for featured images)portrait– Verticalsquarish– Square-ish
Color options:
black_and_white,black,white,yellow,orange,red,purple,magenta,green,teal,blue
Downloading Images
Download Image to Filesystem
download_image() {
local image_url=$1
local output_file=$2
if curl -s -o "$output_file" "$image_url"; then
echo "Downloaded: ${output_file}"
return 0
else
echo "Error: Download failed" >&2
return 1
fi
}
# Usage
image_url="https://images.unsplash.com/photo-xyz?w=1080"
output="/tmp/unsplash-image.jpg"
download_image "$image_url" "$output"
Generate Unique Filename
generate_filename() {
local query=$1
local timestamp=$(date +%Y%m%d_%H%M%S)
local random=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 6)
# Sanitize query (remove spaces, special chars)
local clean_query=$(echo "$query" | tr ' ' '-' | tr -cd '[:alnum:]-')
echo "unsplash-${clean_query}-${timestamp}-${random}.jpg"
}
# Usage
filename=$(generate_filename "mountain landscape")
# Output: unsplash-mountain-landscape-20250325_143022-aB3xY9.jpg
Complete Download Function
fetch_and_download() {
local query=$1
local output_dir=${2:-/tmp}
# Fetch image data
local response=$(curl -s -H "Authorization: Client-ID ${UNSPLASH_KEY}" \
"https://api.unsplash.com/photos/random?query=${query}&orientation=landscape")
# Parse response
local image_url=$(echo "$response" | jq -r '.urls.regular')
local photo_id=$(echo "$response" | jq -r '.id')
if [ "$image_url" = "null" ] || [ -z "$image_url" ]; then
echo "Error: No image found for query '${query}'" >&2
return 1
fi
# Generate filename
local filename=$(generate_filename "$query")
local filepath="${output_dir}/${filename}"
# Download image
if curl -s -o "$filepath" "$image_url"; then
echo "$filepath"
return 0
else
echo "Error: Download failed" >&2
return 1
fi
}
# Usage
image_file=$(fetch_and_download "workspace" "/tmp")
echo "Image saved: ${image_file}"
Importing to WordPress Media Library
WP-CLI Media Import
WP-CLI provides wp media import for adding images to media library.
Basic import:
wp media import /tmp/image.jpg --title="My Image"
With metadata:
wp media import /tmp/image.jpg \
--title="Mountain Landscape" \
--alt="Beautiful mountain sunset" \
--caption="Photo by John Doe on Unsplash" \
--porcelain # Returns attachment ID only
Import Function with Metadata
import_to_wordpress() {
local image_file=$1
local title=$2
local alt_text=$3
local caption=$4
# Import and get attachment ID
local attachment_id=$(wp media import "$image_file" \
--title="$title" \
--alt="$alt_text" \
--caption="$caption" \
--porcelain)
if [ -n "$attachment_id" ]; then
echo "Imported as attachment ID: ${attachment_id}"
echo "$attachment_id"
return 0
else
echo "Error: Import failed" >&2
return 1
fi
}
# Usage
attachment_id=$(import_to_wordpress \
"/tmp/image.jpg" \
"Tech Workspace" \
"Modern laptop on wooden desk" \
"Photo by Jane Smith on Unsplash")
Complete Fetch and Import
fetch_and_import() {
local query=$1
# Fetch image from Unsplash
local response=$(curl -s -H "Authorization: Client-ID ${UNSPLASH_KEY}" \
"https://api.unsplash.com/photos/random?query=${query}&orientation=landscape")
# Parse metadata
local image_url=$(echo "$response" | jq -r '.urls.regular')
local photographer=$(echo "$response" | jq -r '.user.name')
local photographer_url=$(echo "$response" | jq -r '.user.links.html')
local alt_text=$(echo "$response" | jq -r '.alt_description')
local description=$(echo "$response" | jq -r '.description // .alt_description')
# Download to temp file
local temp_file="/tmp/unsplash-$(date +%s).jpg"
curl -s -o "$temp_file" "$image_url"
# Prepare metadata
local title="$description"
local caption="Photo by ${photographer} on Unsplash (${photographer_url})"
# Import to WordPress
local attachment_id=$(wp media import "$temp_file" \
--title="$title" \
--alt="$alt_text" \
--caption="$caption" \
--porcelain)
# Clean up temp file
rm -f "$temp_file"
echo "$attachment_id"
}
# Usage
attachment_id=$(fetch_and_import "coffee shop")
echo "Imported image: ${attachment_id}"
Setting Featured Images
Set Featured Image for Post
wp post meta update POST_ID _thumbnail_id ATTACHMENT_ID
Example:
# Post ID 123, Attachment ID 456
wp post meta update 123 _thumbnail_id 456
Complete Function
set_featured_image() {
local post_id=$1
local attachment_id=$2
if wp post meta update "$post_id" _thumbnail_id "$attachment_id" &>/dev/null; then
echo "Featured image set for post ${post_id}"
return 0
else
echo "Error: Failed to set featured image" >&2
return 1
fi
}
# Usage
set_featured_image 123 456
One-Command Solution
Combine everything:
set_unsplash_featured() {
local post_id=$1
local query=$2
echo "Fetching image for: ${query}"
# Fetch and import
local attachment_id=$(fetch_and_import "$query")
if [ -z "$attachment_id" ]; then
echo "Error: Failed to fetch/import image" >&2
return 1
fi
# Set as featured
if set_featured_image "$post_id" "$attachment_id"; then
echo "✓ Featured image set successfully"
echo "Post ID: ${post_id}"
echo "Attachment ID: ${attachment_id}"
return 0
else
return 1
fi
}
# Usage
set_unsplash_featured 123 "technology workspace"
Handling Attribution
Unsplash Attribution Requirements
Per Unsplash License:
Required:
- Credit photographer by name
- Link to photographer’s Unsplash profile
Good attribution:
“Photo by Photographer Name on Unsplash”
Bad attribution:
“From Unsplash” (missing photographer credit)
Add Attribution to Caption
create_attribution() {
local photographer=$1
local photographer_url=$2
echo "Photo by ${photographer} on Unsplash (${photographer_url})"
}
# Usage
photographer="John Doe"
url="https://unsplash.com/@johndoe"
caption=$(create_attribution "$photographer" "$url")
# Output: Photo by John Doe on Unsplash (https://unsplash.com/@johndoe)
Add Attribution to Post Content
Optionally add attribution directly in post content:
add_attribution_to_post() {
local post_id=$1
local photographer=$2
local photographer_url=$3
# Get current content
local content=$(wp post get "$post_id" --field=content)
# Append attribution
local attribution="<p><em>Featured image by <a href=\"${photographer_url}\">${photographer}</a> on <a href=\"https://unsplash.com\">Unsplash</a></em></p>"
local new_content="${content}\n\n${attribution}"
# Update post
wp post update "$post_id" --post_content="$new_content"
}
Trigger Download Tracking
Unsplash requires triggering download endpoint for analytics:
trigger_download() {
local download_url=$1
curl -s -H "Authorization: Client-ID ${UNSPLASH_KEY}" "$download_url" > /dev/null
}
# Get download URL from API response
download_url=$(echo "$response" | jq -r '.links.download_location')
trigger_download "$download_url"
Important: This is required by Unsplash API guidelines.
Complete Automation Script
Here’s the full production-ready script:
#!/bin/bash
#
# Unsplash WordPress Integration Script
# Fetches images from Unsplash and sets as WordPress featured images
#
set -euo pipefail
#############################################
# CONFIGURATION
#############################################
# Load API key from config file
if [ -f ~/.unsplash-config ]; then
source ~/.unsplash-config
fi
UNSPLASH_KEY="${UNSPLASH_ACCESS_KEY:-}"
TEMP_DIR="/tmp/unsplash-wp"
#############################################
# FUNCTIONS
#############################################
check_dependencies() {
local missing=()
command -v curl &>/dev/null || missing+=("curl")
command -v jq &>/dev/null || missing+=("jq")
command -v wp &>/dev/null || missing+=("wp-cli")
if [ then
echo "Error: Missing dependencies: ${missing[*]}" >&2
exit 1
fi
if [ -z "$UNSPLASH_KEY" ]; then
echo "Error: UNSPLASH_ACCESS_KEY not set" >&2
echo "Set it in ~/.unsplash-config or environment" >&2
exit 1
fi
}
fetch_unsplash_image() {
local query=$1
local orientation=${2:-landscape}
local url="https://api.unsplash.com/photos/random"
url="${url}?query=${query}&orientation=${orientation}"
local response=$(curl -s -H "Authorization: Client-ID ${UNSPLASH_KEY}" "$url")
# Check for errors
local errors=$(echo "$response" | jq -r '.errors // empty')
if [ -n "$errors" ]; then
echo "API Error: $errors" >&2
return 1
fi
echo "$response"
}
download_image() {
local image_url=$1
local output_file=$2
if curl -s -L -o "$output_file" "$image_url"; then
return 0
else
return 1
fi
}
import_to_media_library() {
local image_file=$1
local metadata=$2
local title=$(echo "$metadata" | jq -r '.title')
local alt=$(echo "$metadata" | jq -r '.alt')
local caption=$(echo "$metadata" | jq -r '.caption')
local attachment_id=$(wp media import "$image_file" \
--title="$title" \
--alt="$alt" \
--caption="$caption" \
--porcelain 2>/dev/null)
echo "$attachment_id"
}
set_featured_image_for_post() {
local post_id=$1
local attachment_id=$2
wp post meta update "$post_id" _thumbnail_id "$attachment_id" &>/dev/null
}
trigger_download_endpoint() {
local download_url=$1
curl -s -H "Authorization: Client-ID ${UNSPLASH_KEY}" "$download_url" > /dev/null
}
#############################################
# MAIN FUNCTION
#############################################
set_unsplash_featured() {
local post_id=$1
local query=$2
local orientation=${3:-landscape}
echo "================================================"
echo "Unsplash Featured Image Automation"
echo "================================================"
echo "Post ID: ${post_id}"
echo "Query: ${query}"
echo "Orientation: ${orientation}"
echo "================================================"
# Verify post exists
if ! wp post get "$post_id" &>/dev/null; then
echo "Error: Post ${post_id} not found" >&2
return 1
fi
# Fetch image from Unsplash
echo "Fetching image from Unsplash..."
local response=$(fetch_unsplash_image "$query" "$orientation")
if [ $? -ne 0 ]; then
echo "Error: Failed to fetch image" >&2
return 1
fi
# Parse response
local image_url=$(echo "$response" | jq -r '.urls.regular')
local photographer=$(echo "$response" | jq -r '.user.name')
local photographer_url=$(echo "$response" | jq -r '.user.links.html')
local alt_text=$(echo "$response" | jq -r '.alt_description // "Image from Unsplash"')
local description=$(echo "$response" | jq -r '.description // .alt_description')
local download_endpoint=$(echo "$response" | jq -r '.links.download_location')
echo "Found: ${description}"
echo "By: ${photographer}"
# Create temp directory
mkdir -p "$TEMP_DIR"
# Download image
local temp_file="${TEMP_DIR}/unsplash-$(date +%s).jpg"
echo "Downloading image..."
if ! download_image "$image_url" "$temp_file"; then
echo "Error: Download failed" >&2
return 1
fi
# Prepare metadata
local caption="Photo by <a href=\"${photographer_url}\">${photographer}</a> on <a href=\"https://unsplash.com\">Unsplash</a>"
local metadata=$(jq -n \
--arg title "$description" \
--arg alt "$alt_text" \
--arg caption "$caption" \
'{title: $title, alt: $alt, caption: $caption}')
# Import to WordPress
echo "Importing to media library..."
local attachment_id=$(import_to_media_library "$temp_file" "$metadata")
if [ -z "$attachment_id" ]; then
echo "Error: Import failed" >&2
rm -f "$temp_file"
return 1
fi
echo "Imported as attachment ${attachment_id}"
# Set as featured image
echo "Setting as featured image..."
if set_featured_image_for_post "$post_id" "$attachment_id"; then
echo "✓ Featured image set successfully"
else
echo "Error: Failed to set featured image" >&2
rm -f "$temp_file"
return 1
fi
# Trigger download tracking (required by Unsplash)
trigger_download_endpoint "$download_endpoint"
# Clean up
rm -f "$temp_file"
echo "================================================"
echo "SUCCESS!"
echo "Post: ${post_id}"
echo "Attachment: ${attachment_id}"
echo "Photographer: ${photographer}"
echo "================================================"
return 0
}
#############################################
# SCRIPT ENTRY POINT
#############################################
# Check dependencies
check_dependencies
# Parse arguments
if [ $# -lt 2 ]; then
echo "Usage: $0 <post_id> <search_query> [orientation]"
echo ""
echo "Examples:"
echo " $0 123 'technology workspace'"
echo " $0 456 'coffee shop' portrait"
echo ""
exit 1
fi
POST_ID=$1
QUERY=$2
ORIENTATION=${3:-landscape}
# Run main function
set_unsplash_featured "$POST_ID" "$QUERY" "$ORIENTATION"
exit $?
Usage
# Save as unsplash-wp.sh
chmod +x unsplash-wp.sh
# Set featured image for post
./unsplash-wp.sh 123 "technology workspace"
# Portrait orientation
./unsplash-wp.sh 456 "coffee shop interior" portrait
# Multiple keywords
./unsplash-wp.sh 789 "mountain sunset landscape"
Advanced Features
Bulk Set Featured Images
Process multiple posts:
# Get all posts without featured images
posts=$(wp post list --post_type=post --meta_key=_thumbnail_id --meta_compare=NOT EXISTS --field=ID)
for post_id in $posts; do
# Get post title or category for query
title=$(wp post get $post_id --field=title)
# Set featured image
./unsplash-wp.sh $post_id "$title"
sleep 2 # Rate limiting
done
Smart Query from Post Content
Extract keywords from post:
get_query_from_post() {
local post_id=$1
# Get post title
local title=$(wp post get $post_id --field=title)
# Get first category
local category=$(wp post term list $post_id category --field=name --format=csv | head -1)
# Combine for better results
echo "${category} ${title}"
}
# Usage
query=$(get_query_from_post 123)
./unsplash-wp.sh 123 "$query"
Fallback to Default Images
set_featured_with_fallback() {
local post_id=$1
local query=$2
local fallback_query="abstract background"
if ! ./unsplash-wp.sh $post_id "$query"; then
echo "Primary query failed, trying fallback..."
./unsplash-wp.sh $post_id "$fallback_query"
fi
}
Error Handling
API Error Responses
Handle common errors:
handle_api_response() {
local response=$1
# Check for rate limit
local rate_limit=$(echo "$response" | jq -r '.errors[0] // empty' | grep -i "rate limit")
if [ -n "$rate_limit" ]; then
echo "Error: API rate limit reached" >&2
echo "Wait 1 hour or upgrade to production API" >&2
return 1
fi
# Check for invalid query
local invalid=$(echo "$response" | jq -r '.errors[0] // empty')
if [ -n "$invalid" ]; then
echo "Error: $invalid" >&2
return 1
fi
return 0
}
Network Errors
download_with_retry() {
local url=$1
local output=$2
local max_attempts=3
local attempt=1
while [ $attempt -le $max_attempts ]; do
echo "Download attempt ${attempt}/${max_attempts}"
if curl -s -L -o "$output" --connect-timeout 10 "$url"; then
return 0
fi
attempt=$((attempt + 1))
sleep 2
done
echo "Error: Download failed after ${max_attempts} attempts" >&2
return 1
}
Rate Limiting
Unsplash Rate Limits
- Demo: 50 requests/hour
- Production: 5,000 requests/hour
Implement Rate Limiting
check_rate_limit() {
local last_request_file="/tmp/unsplash-last-request"
local min_interval=72 # 50 requests/hour = 72 seconds between requests
if [ -f "$last_request_file" ]; then
local last_request=$(cat "$last_request_file")
local now=$(date +%s)
local elapsed=$((now - last_request))
if [ $elapsed -lt $min_interval ]; then
local wait=$((min_interval - elapsed))
echo "Rate limiting: waiting ${wait} seconds..."
sleep $wait
fi
fi
# Update last request time
date +%s > "$last_request_file"
}
# Call before API requests
check_rate_limit
Monitor Usage
Check remaining requests:
response=$(curl -I -H "Authorization: Client-ID ${UNSPLASH_KEY}" \
"https://api.unsplash.com/photos/random")
remaining=$(echo "$response" | grep -i "X-Ratelimit-Remaining" | cut -d: -f2 | tr -d ' \r')
echo "Remaining requests: ${remaining}"
Integration with Publishing Pipeline
Automated Blog Publishing
Combine with content automation:
publish_post_with_image() {
local title=$1
local content=$2
local query=$3
# Create post
local post_id=$(wp post create \
--post_title="$title" \
--post_content="$content" \
--post_status=publish \
--porcelain)
# Set featured image from Unsplash
./unsplash-wp.sh $post_id "$query"
echo "Published post: ${post_id}"
}
# Usage
publish_post_with_image \
"10 Best Productivity Tools" \
"Content here..." \
"productivity workspace"
Integration with AI Content
# Get AI-generated content
content=$(call_ai_api "Write about productivity tools")
# Extract keywords for image
keywords=$(echo "$content" | extract_keywords) # Custom function
# Create post
post_id=$(wp post create --post_title="..." --post_content="$content" --porcelain)
# Set Unsplash featured image
./unsplash-wp.sh $post_id "$keywords"
Learn more: Automated Blog Publishing with AI
Troubleshooting
Issue 1: “jq: command not found”
Solution:
# Ubuntu/Debian
sudo apt-get install jq
# macOS
brew install jq
# CentOS
sudo yum install jq
Issue 2: “401 Unauthorized”
Problem: Invalid API key
Solutions:
- Verify API key is correct
- Check environment variable is set:
echo $UNSPLASH_ACCESS_KEY
- Regenerate API key in Unsplash dashboard
Issue 3: No Images Found
Problem: Query returns no results
Solutions:
- Simplify query (use broader terms)
- Try different keywords
- Check query isn’t too specific
# Too specific (may fail)
query="red ferrari on mountain road at sunset"
# Better (broader)
query="sports car"
Issue 4: Rate Limit Exceeded
Problem: “Rate Limit Exceeded” error
Solutions:
- Wait 1 hour for demo API reset
- Apply for production API (5,000 req/hour)
- Implement rate limiting in your script
Issue 5: Import Failed
Problem: wp media import fails
Solutions:
- Check file permissions:
ls -la /tmp/image.jpg
chmod 644 /tmp/image.jpg
- Verify uploads directory is writable:
wp media regenerate --dry-run
- Check file size (Unsplash regular = ~500KB, should be fine)
Next Steps
Congratulations! You’ve built a complete Unsplash + WordPress automation system.
Enhance Your Integration
- Automated Blog Publishing Pipeline – Combine with AI content
- Custom WP-CLI Commands – Build
wp unsplashcommand - Bash Functions – Refactor into reusable library
Related Guides
- WordPress REST API Integration – Advanced API techniques
- AI Content Generation – Complete publishing automation
- WordPress Automation – More automation examples
Build the Complete Pipeline
This Unsplash integration is one piece of a complete automated publishing system:
- Generate content with AI
- Fetch featured image from Unsplash ← You just learned this
- Schedule and publish post
- Optimize SEO automatically
Join WPCLI Mastery to build the complete system:
- Full automated blog publishing pipeline
- AI + Unsplash + WP-CLI integration
- Production-ready scripts and templates
- Early bird pricing ($99 vs $199)
Conclusion
Automating featured images with Unsplash API and WP-CLI saves hours of manual work while ensuring every post has professional, high-quality imagery. The script you built today can process thousands of posts automatically.
Key takeaways:
- Unsplash API provides free, high-quality images
- curl + jq makes API integration simple
- WP-CLI
media importhandles WordPress integration - Proper attribution is required (and easy to automate)
- Rate limiting prevents API issues
- Integration with publishing pipelines creates powerful automation
The image automation you built today becomes even more powerful when combined with AI content generation for a complete hands-free publishing system.
Ready to implement? Start with the complete script and customize for your workflow.
Questions about Unsplash + WordPress automation? Drop a comment below!
Found this helpful? Share with WordPress developers automating content.
Next: Build a complete WordPress CI/CD pipeline with GitHub Actions that includes automated image fetching.
