AI-Powered Image Search
Search your images using natural language with semantic search powered by OpenAI embeddings.
Prerequisites
To use AI-powered search, you need:
- AI Analysis Enabled - Contact support to enable this feature
- OpenAI API Key - Configured in your account settings
- Analyzed Images - Images are automatically analyzed on upload
How It Works
- When you upload an image, AI generates a caption describing it
- The caption is converted to a vector embedding
- When you search, your query is also converted to an embedding
- Similar images are found using vector similarity matching
Basic Search
javascript
const response = await fetch(
'https://api.reimage.dev/get/search?q=red sports car',
{
headers: {
'Authorization': `Bearer ${process.env.REIMAGE_API_KEY}`
}
}
);
const results = await response.json();
console.log(`Found ${results.count} images`);Search Parameters
javascript
async function searchImages(query, options = {}) {
const params = new URLSearchParams({
q: query,
threshold: options.threshold || 0.7, // 0.0 to 1.0
limit: options.limit || 10 // Max results
});
const response = await fetch(
`https://api.reimage.dev/get/search?${params}`,
{
headers: {
'Authorization': `Bearer ${process.env.REIMAGE_API_KEY}`
}
}
);
return await response.json();
}
// Usage
const results = await searchImages('sunset over ocean', {
threshold: 0.7, // Similarity threshold
limit: 20 // Return up to 20 results
});Response Format
json
{
"query": "red sports car",
"count": 5,
"objects": [
"https://files.reimage.dev/abc123/xyz789/"
],
"urls": [
"https://files.reimage.dev/abc123/xyz789/original.webp"
],
"thumbnails": [
"https://files.reimage.dev/abc123/xyz789/h-200_w-200.webp"
],
"captions": [
"A red Ferrari parked on a mountain road"
],
"similarities": [
0.923
]
}Similarity Threshold
The threshold controls how strict the matching is:
- 0.9 - 1.0: Very strict, near-exact matches only
- 0.7 - 0.9: Balanced (recommended)
- 0.5 - 0.7: More lenient, broader results
- 0.0 - 0.5: Very broad, may include unrelated images
javascript
// Strict search
const exact = await searchImages('red car', { threshold: 0.9 });
// Returns only very similar matches
// Broad search
const broad = await searchImages('red car', { threshold: 0.6 });
// Returns more results, less similarReact Search Component
jsx
import { useState } from 'react';
function SemanticSearch() {
const [query, setQuery] = useState('');
const [results, setResults] = useState(null);
const [loading, setLoading] = useState(false);
const [threshold, setThreshold] = useState(0.7);
const handleSearch = async (e) => {
e.preventDefault();
if (!query.trim()) return;
setLoading(true);
try {
const params = new URLSearchParams({
q: query,
threshold: threshold.toString(),
limit: '20'
});
const response = await fetch(
`https://api.reimage.dev/get/search?${params}`,
{
headers: {
'Authorization': `Bearer ${process.env.REACT_APP_REIMAGE_API_KEY}`
}
}
);
if (!response.ok) {
throw new Error('Search failed');
}
const data = await response.json();
setResults(data);
} catch (error) {
alert(error.message);
} finally {
setLoading(false);
}
};
return (
<div className="semantic-search">
<form onSubmit={handleSearch}>
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Describe what you're looking for..."
disabled={loading}
/>
<div className="threshold-control">
<label>
Similarity: {(threshold * 100).toFixed(0)}%
<input
type="range"
min="0.5"
max="1.0"
step="0.05"
value={threshold}
onChange={(e) => setThreshold(parseFloat(e.target.value))}
/>
</label>
</div>
<button type="submit" disabled={loading}>
{loading ? 'Searching...' : 'Search'}
</button>
</form>
{results && (
<div className="results">
<h3>Found {results.count} images</h3>
<div className="image-grid">
{results.urls.map((url, i) => (
<div key={i} className="result-card">
<img
src={results.thumbnails[i]}
alt={results.captions[i]}
/>
<p className="caption">{results.captions[i]}</p>
<div className="similarity">
Match: {(results.similarities[i] * 100).toFixed(0)}%
</div>
</div>
))}
</div>
</div>
)}
</div>
);
}Example Queries
Objects and Scenes
javascript
await searchImages('red sports car on mountain road');
await searchImages('sunset over the ocean');
await searchImages('modern office interior');
await searchImages('coffee cup on wooden table');People and Actions
javascript
await searchImages('person wearing sunglasses');
await searchImages('smiling woman in business suit');
await searchImages('athlete running');
await searchImages('child playing with dog');Products
javascript
await searchImages('blue sneakers');
await searchImages('silver laptop');
await searchImages('wooden chair');
await searchImages('red backpack');Abstract Concepts
javascript
await searchImages('happiness');
await searchImages('technology');
await searchImages('nature');
await searchImages('celebration');Search Tips
Be Specific
javascript
// ✅ Good - specific
await searchImages('red Ferrari parked in front of modern building');
// ❌ Too vague
await searchImages('car');Use Descriptive Language
javascript
// ✅ Good - descriptive
await searchImages('golden retriever playing in grassy park');
// ❌ Too simple
await searchImages('dog');Include Context
javascript
// ✅ Good - includes context
await searchImages('laptop on desk with coffee and notepad');
// ❌ Missing context
await searchImages('laptop');Combining with Traditional Search
Use both semantic search and tag filtering:
javascript
// First, filter by tags
const taggedImages = await fetch(
'https://api.reimage.dev/get/?tags=product',
{ headers: { 'Authorization': `Bearer ${API_KEY}` } }
).then(r => r.json());
// Then, search within those results using semantic search
const searchResults = await searchImages('red shoes');Error Handling
javascript
async function searchWithErrorHandling(query) {
try {
const response = await fetch(
`https://api.reimage.dev/get/search?q=${encodeURIComponent(query)}`,
{
headers: {
'Authorization': `Bearer ${process.env.REIMAGE_API_KEY}`
}
}
);
if (response.status === 403) {
const error = await response.json();
if (error.error.includes('not enabled')) {
throw new Error('AI search is not enabled for your account');
}
if (error.error.includes('API key')) {
throw new Error('Please configure your OpenAI API key');
}
}
if (!response.ok) {
throw new Error('Search failed');
}
return await response.json();
} catch (error) {
console.error('Search error:', error);
throw error;
}
}Performance Considerations
- First search may be slower as embeddings are generated
- Subsequent searches are fast (< 100ms)
- Results are not cached - each search is real-time
- Limit results to improve performance
Viewing Image Captions
Captions are included in search results:
javascript
const results = await searchImages('red car');
results.captions.forEach((caption, i) => {
console.log(`Image ${i + 1}: ${caption}`);
console.log(`Similarity: ${results.similarities[i]}`);
console.log(`URL: ${results.urls[i]}`);
});Advanced: Custom Similarity Algorithm
The similarity score is calculated using cosine similarity between embeddings:
javascript
// Results are sorted by similarity (highest first)
const results = await searchImages('sunset');
// Filter by minimum similarity
const highQualityMatches = results.urls.filter((_, i) =>
results.similarities[i] > 0.85
);Limitations
- Only works with images that have been analyzed
- Requires OpenAI API key configuration
- Analysis happens on upload (existing images not analyzed)
- English queries work best
- AI-generated captions may not be perfect
Cost Considerations
AI analysis uses your OpenAI API credits:
- Caption generation: ~$0.0001 per image
- Search query embedding: ~$0.00001 per search
Configure your OpenAI API key in account settings to enable this feature.
Next Steps
- Search API Reference - Detailed API documentation
- Upload API - Upload images for analysis
- Get Images API - Traditional tag-based filtering