Skip to main content
RapidDev - Software Development Agency
replit-integrationsStandard API Integration

How to Integrate Replit with Pixabay API

To integrate Replit with the Pixabay API, register a free account at pixabay.com/api/docs, get your API key, store it in Replit Secrets (lock icon πŸ”’), and use Python or Node.js to search millions of free images, videos, and illustrations. No OAuth required β€” a single API key grants access to the full catalog under the Pixabay Content License.

What you'll learn

  • How to register for a Pixabay API key and understand the rate limits for free accounts
  • How to store the Pixabay API key securely in Replit Secrets
  • How to search Pixabay images, videos, and illustrations using Python and Node.js
  • How to filter results by category, color, orientation, and media type
  • How to serve Pixabay image URLs safely from a backend route to avoid key exposure
Book a free consultation
4.9Clutch rating ⭐
600+Happy partners
17+Countries served
190+Team members
Beginner13 min read20 minutesSocialMarch 2026RapidDev Engineering Team
TL;DR

To integrate Replit with the Pixabay API, register a free account at pixabay.com/api/docs, get your API key, store it in Replit Secrets (lock icon πŸ”’), and use Python or Node.js to search millions of free images, videos, and illustrations. No OAuth required β€” a single API key grants access to the full catalog under the Pixabay Content License.

Why Connect Replit to the Pixabay API?

Pixabay is one of the most accessible free media APIs available. Unlike premium stock services that require paid licenses or lengthy application approvals, Pixabay allows any registered user to access millions of royalty-free images, videos, and vector illustrations with a simple API key. This makes it ideal for prototypes, content-heavy apps, blog platforms, and tools that need to display contextual images without licensing overhead.

The Pixabay API supports searching by keyword, category, color, orientation, and media type. Results include multiple image sizes (preview, webformat, and full) along with metadata such as tags, user, views, downloads, and likes. The free tier allows up to 100 requests per 60 seconds per API key, which is sufficient for most interactive apps. Images are served directly from Pixabay's CDN, so you only need to relay the image URLs β€” your Replit backend handles the API call and your frontend displays the images.

Because Pixabay uses plain API key authentication, there is no OAuth token management to worry about. Store the key in Replit Secrets (lock icon πŸ”’ in the sidebar), read it at runtime with os.environ or process.env, and append it to your API requests. This is one of the quickest media API integrations you can build in Replit.

Integration method

Standard API Integration

You connect Replit to Pixabay by registering a free account, obtaining an API key from the Pixabay API documentation page, and storing it in Replit Secrets. Your server-side Python or Node.js code appends the key as a query parameter on every request to the Pixabay REST API. Because Pixabay uses simple API key auth with no OAuth token flow, setup takes only minutes and the same key works for images, videos, and vector illustrations.

Prerequisites

  • A Replit account with a Python or Node.js project created
  • A free Pixabay account at https://pixabay.com (required to access the API)
  • An API key from https://pixabay.com/api/docs after logging in
  • Basic familiarity with making HTTP requests in Python (requests library) or Node.js (axios or node-fetch)

Step-by-step guide

1

Get Your Pixabay API Key

Go to https://pixabay.com and create a free account or log in. Once logged in, navigate to https://pixabay.com/api/docs β€” this page shows your personal API key in the first code example displayed at the top of the documentation. The key is a numeric string (e.g., 12345678-abcdef1234567890abcdef12). Pixabay API access is available to all registered users at no cost. The free tier allows up to 100 requests per 60 seconds per API key. For most interactive applications, this rate limit is more than adequate. If you need higher throughput, contact Pixabay to discuss increased limits for production applications. The Pixabay API does not use OAuth β€” the API key is the only credential you need. It acts as a query parameter called 'key' appended to every request. There is no token expiry to manage, no refresh flow, and no scopes to configure. This simplicity is one of Pixabay's biggest advantages for beginner integrations.

Pro tip: Your API key is visible immediately after logging in at pixabay.com/api/docs β€” you do not need to create a separate application or wait for approval.

Expected result: You have a Pixabay API key (a long alphanumeric string) ready to store in Replit.

2

Store the API Key in Replit Secrets

Open your Replit project and click the lock icon πŸ”’ in the left sidebar to open the Secrets pane. Click 'Add a new secret' and enter: - Key: PIXABAY_API_KEY - Value: your Pixabay API key Click 'Add Secret' to save. Replit encrypts this value and injects it as an environment variable when your application runs. You access it in Python as os.environ['PIXABAY_API_KEY'] and in Node.js as process.env.PIXABAY_API_KEY. Even though Pixabay's API key is lower risk than payment credentials, storing it in Replit Secrets is still best practice. It prevents the key from appearing in your source code (which could be made public), and Replit's Secret Scanner will alert you if a key accidentally ends up in a committed file. Always access the key at runtime from the environment rather than hardcoding it.

Pro tip: After adding the secret, restart your Repl to ensure the environment variable is injected into the running process.

Expected result: PIXABAY_API_KEY appears in the Replit Secrets pane with the value hidden.

3

Search Images with Python

Install the requests library in your Replit Shell if it is not already available by running 'pip install requests'. The Pixabay API base URL is https://pixabay.com/api/ for images and illustrations, and https://pixabay.com/api/videos/ for video content. Query parameters include 'q' (search term), 'image_type' (all, photo, illustration, vector), 'orientation' (all, horizontal, vertical), 'category', 'min_width', 'min_height', 'colors', 'per_page' (3-200, default 20), and 'page'. The Flask server below exposes two endpoints: /search for image queries and /video for video queries. Both accept a 'query' parameter and return a simplified response with image URLs and metadata. The API key is read from the environment and appended server-side, so the frontend never sees it.

app.py
1import os
2import requests
3from flask import Flask, request, jsonify
4
5app = Flask(__name__)
6
7PIXABAY_API_KEY = os.environ["PIXABAY_API_KEY"]
8IMAGE_API_URL = "https://pixabay.com/api/"
9VIDEO_API_URL = "https://pixabay.com/api/videos/"
10
11
12def search_images(query: str, image_type: str = "all",
13 orientation: str = "all", per_page: int = 20,
14 page: int = 1) -> dict:
15 """Search Pixabay for images, illustrations, or vectors."""
16 params = {
17 "key": PIXABAY_API_KEY,
18 "q": query,
19 "image_type": image_type, # all, photo, illustration, vector
20 "orientation": orientation, # all, horizontal, vertical
21 "per_page": min(max(per_page, 3), 200),
22 "page": page,
23 "safesearch": "true"
24 }
25 resp = requests.get(IMAGE_API_URL, params=params)
26 resp.raise_for_status()
27 return resp.json()
28
29
30def search_videos(query: str, per_page: int = 20, page: int = 1) -> dict:
31 """Search Pixabay for video content."""
32 params = {
33 "key": PIXABAY_API_KEY,
34 "q": query,
35 "per_page": min(max(per_page, 3), 200),
36 "page": page
37 }
38 resp = requests.get(VIDEO_API_URL, params=params)
39 resp.raise_for_status()
40 return resp.json()
41
42
43@app.route("/search")
44def search():
45 query = request.args.get("query", "")
46 image_type = request.args.get("type", "all")
47 orientation = request.args.get("orientation", "all")
48 page = int(request.args.get("page", 1))
49 per_page = int(request.args.get("per_page", 20))
50
51 if not query:
52 return jsonify({"error": "query parameter is required"}), 400
53
54 data = search_images(query, image_type, orientation, per_page, page)
55 results = []
56 for hit in data.get("hits", []):
57 results.append({
58 "id": hit["id"],
59 "tags": hit["tags"],
60 "preview_url": hit["previewURL"],
61 "web_url": hit["webformatURL"],
62 "large_url": hit.get("largeImageURL", ""),
63 "user": hit["user"],
64 "views": hit["views"],
65 "downloads": hit["downloads"],
66 "page_url": hit["pageURL"]
67 })
68 return jsonify({"total": data.get("totalHits", 0), "results": results})
69
70
71@app.route("/video")
72def video():
73 query = request.args.get("query", "")
74 if not query:
75 return jsonify({"error": "query parameter is required"}), 400
76 data = search_videos(query)
77 results = []
78 for hit in data.get("hits", []):
79 videos = hit.get("videos", {})
80 results.append({
81 "id": hit["id"],
82 "tags": hit["tags"],
83 "user": hit["user"],
84 "duration": hit["duration"],
85 "medium_url": videos.get("medium", {}).get("url", ""),
86 "small_url": videos.get("small", {}).get("url", ""),
87 "page_url": hit["pageURL"]
88 })
89 return jsonify({"total": data.get("totalHits", 0), "results": results})
90
91
92if __name__ == "__main__":
93 app.run(host="0.0.0.0", port=3000, debug=True)

Pro tip: The 'webformatURL' field is a web-optimized JPEG capped at 1920px β€” use this for display. The 'largeImageURL' provides higher resolution but is not available on all images. The 'previewURL' is a small 150px thumbnail, good for gallery grids.

Expected result: GET /search?query=mountain returns a JSON array of image results with preview and full-size URLs.

4

Build a Node.js Pixabay Server

For Node.js projects, install axios with 'npm install axios express'. The pattern is the same as Python: read the API key from the environment, build request parameters server-side, and forward only the cleaned image URLs to the frontend. This prevents the API key from being exposed in browser network requests. The server below handles both image and video searches, implements basic pagination, and returns a consistent response shape. Note that Pixabay returns a 'totalHits' field capped at 500 regardless of the actual total results β€” this is a Pixabay API limitation, not an error.

server.js
1const express = require('express');
2const axios = require('axios');
3
4const app = express();
5app.use(express.json());
6
7const PIXABAY_API_KEY = process.env.PIXABAY_API_KEY;
8const IMAGE_URL = 'https://pixabay.com/api/';
9const VIDEO_URL = 'https://pixabay.com/api/videos/';
10
11// Search images
12app.get('/search', async (req, res) => {
13 const {
14 query,
15 type = 'all',
16 orientation = 'all',
17 page = 1,
18 per_page = 20
19 } = req.query;
20
21 if (!query) {
22 return res.status(400).json({ error: 'query parameter is required' });
23 }
24
25 try {
26 const { data } = await axios.get(IMAGE_URL, {
27 params: {
28 key: PIXABAY_API_KEY,
29 q: query,
30 image_type: type,
31 orientation,
32 per_page: Math.min(Math.max(Number(per_page), 3), 200),
33 page: Number(page),
34 safesearch: 'true'
35 }
36 });
37
38 const results = data.hits.map(hit => ({
39 id: hit.id,
40 tags: hit.tags,
41 previewUrl: hit.previewURL,
42 webUrl: hit.webformatURL,
43 largeUrl: hit.largeImageURL || '',
44 user: hit.user,
45 views: hit.views,
46 downloads: hit.downloads,
47 pageUrl: hit.pageURL
48 }));
49
50 res.json({ total: data.totalHits, results });
51 } catch (err) {
52 const status = err.response?.status || 500;
53 res.status(status).json({ error: err.response?.data || err.message });
54 }
55});
56
57// Search videos
58app.get('/video', async (req, res) => {
59 const { query, page = 1, per_page = 20 } = req.query;
60
61 if (!query) {
62 return res.status(400).json({ error: 'query parameter is required' });
63 }
64
65 try {
66 const { data } = await axios.get(VIDEO_URL, {
67 params: {
68 key: PIXABAY_API_KEY,
69 q: query,
70 per_page: Math.min(Math.max(Number(per_page), 3), 200),
71 page: Number(page)
72 }
73 });
74
75 const results = data.hits.map(hit => ({
76 id: hit.id,
77 tags: hit.tags,
78 user: hit.user,
79 duration: hit.duration,
80 mediumUrl: hit.videos?.medium?.url || '',
81 smallUrl: hit.videos?.small?.url || '',
82 pageUrl: hit.pageURL
83 }));
84
85 res.json({ total: data.totalHits, results });
86 } catch (err) {
87 const status = err.response?.status || 500;
88 res.status(status).json({ error: err.response?.data || err.message });
89 }
90});
91
92app.listen(3000, '0.0.0.0', () => {
93 console.log('Pixabay integration server running on port 3000');
94});

Pro tip: Pixabay's totalHits is capped at 500. If your UI needs to display 'Found 10,000 results', use the 'total' field from the raw API response which is uncapped, but pagination is only supported up to 500 results.

Expected result: GET /search?query=sunset returns a JSON object with total count and an array of image results with URLs and metadata.

5

Deploy and Configure the .replit File

Click the Deploy button in Replit and choose Autoscale deployment. Pixabay image search is a request-driven workload with no persistent background tasks, making Autoscale the most cost-effective choice. Autoscale scales to zero when no requests are coming in and scales up instantly when queries arrive. In your .replit configuration file, set the run command to match your language. For Node.js, that is 'node server.js'. For Python, it is 'python app.py'. Also configure the port mapping so Replit routes external traffic to your server: After deploying, your Pixabay search endpoint will be available at your Replit deployment URL. Test it by visiting /search?query=forest in your browser β€” you should receive JSON results with image URLs. The API key remains hidden in Replit Secrets and is never exposed to clients.

.replit
1[[ports]]
2internalPort = 3000
3externalPort = 80
4
5[deployment]
6run = ["node", "server.js"]
7deploymentTarget = "cloudrun"

Pro tip: Use Autoscale (not Reserved VM) for Pixabay search β€” the workload is purely reactive. Reserved VM is better for always-on services like bots or queues.

Expected result: Your deployed Replit app serves Pixabay search results at the public deployment URL with the API key securely stored in Secrets.

Common use cases

Contextual Blog Image Suggestions

A Replit-backed blogging tool searches Pixabay for images matching a blog post's title or topic, presents a grid of free options to the writer, and inserts the chosen image URL into the post's featured image field. Because Pixabay images are free to use without attribution requirements in most cases, writers can publish immediately without licensing checks.

Replit Prompt

Build a Flask endpoint that accepts a blog topic keyword, queries the Pixabay API for the top 12 horizontal images, and returns a JSON array of preview URLs and Pixabay page links.

Copy this prompt to try it in Replit

Automated Social Media Image Finder

A Replit automation script receives a list of scheduled social media posts, extracts keywords from each post's text, fetches matching Pixabay images for each, and saves the best-matching image URL alongside each post for the scheduler to attach. This saves time in the content pipeline by auto-suggesting visuals for every post.

Replit Prompt

Create a Node.js script that reads a CSV of social media captions, queries Pixabay for one matching image per caption, and outputs a new CSV with an added column for the image URL.

Copy this prompt to try it in Replit

Category-Based Illustration Gallery

A Replit web app displays a browsable illustration gallery powered by Pixabay, letting users filter by category (nature, technology, business, etc.) and media type (photo, illustration, or vector). The backend handles Pixabay pagination so the frontend can implement infinite scroll without exposing the API key.

Replit Prompt

Write an Express server with a /gallery route that accepts category, image_type, and page parameters, fetches results from Pixabay, and returns paginated image data.

Copy this prompt to try it in Replit

Troubleshooting

HTTP 400 Bad Request when querying the Pixabay API

Cause: The API key is missing from the request, malformed, or the API key value in Replit Secrets contains extra whitespace or quotes.

Solution: Open the Replit Secrets pane and verify the PIXABAY_API_KEY value contains only the raw key string with no surrounding quotes or spaces. Print the key value in your code during debugging (print(repr(os.environ['PIXABAY_API_KEY']))) to check for invisible characters.

typescript
1# Debug: check for extra whitespace
2import os
3key = os.environ.get('PIXABAY_API_KEY', '')
4print(f'Key length: {len(key)}, repr: {repr(key[:10])}')

Empty results array even though the search term should match images

Cause: Pixabay search uses exact phrase matching by default. Multi-word queries with special characters may return zero results, or the safesearch filter may be excluding some content.

Solution: Simplify the query to one or two keywords and URL-encode special characters properly. The requests library and axios handle URL encoding automatically, but manually constructed URLs may not. Also try removing the safesearch parameter to see if that is filtering out results.

typescript
1# Try a broad single-keyword query first
2params = {
3 'key': PIXABAY_API_KEY,
4 'q': 'nature', # start simple
5 'per_page': 5
6}

Rate limit errors (HTTP 429) after many searches

Cause: The Pixabay free API allows 100 requests per 60 seconds per key. High-frequency searching, pagination loops, or automated scripts can hit this limit quickly.

Solution: Implement caching for repeated queries using a dictionary keyed on the search term. Cache results for 5-10 minutes to avoid redundant requests. For batch processing scripts, add a short sleep between requests to stay within rate limits.

typescript
1import time
2cache = {}
3
4def cached_search(query, **kwargs):
5 if query in cache and time.time() - cache[query]['ts'] < 300:
6 return cache[query]['data']
7 data = search_images(query, **kwargs)
8 cache[query] = {'data': data, 'ts': time.time()}
9 return data

PIXABAY_API_KEY environment variable returns None or KeyError

Cause: The secret was added after the Repl was started without a restart, or the secret name in the code does not exactly match the key name in Replit Secrets (case-sensitive).

Solution: Restart the Repl after adding a new secret β€” Replit injects secrets at startup. Also verify the exact key name in the Secrets pane matches what your code references. PIXABAY_API_KEY and pixabay_api_key are different names.

Best practices

  • Store PIXABAY_API_KEY in Replit Secrets (lock icon πŸ”’) and never include it in client-side JavaScript or HTML.
  • Always proxy Pixabay API calls through your Replit backend β€” never call the Pixabay API directly from the browser, as that would expose your key.
  • Cache search results for popular or repeated queries to stay within the 100 requests/60 seconds rate limit.
  • Use the 'webformatURL' for display (web-optimized JPEG up to 1920px) and 'previewURL' for thumbnails in grids β€” avoid requesting 'largeImageURL' unless high resolution is truly needed.
  • Include the Pixabay page link (pageURL field) alongside displayed images so users can visit the original page for full attribution and licensing details.
  • Use the 'safesearch=true' parameter in production apps to prevent adult content from appearing in search results.
  • Deploy on Autoscale rather than Reserved VM for image search APIs β€” Autoscale is more cost-efficient for request-driven workloads with variable traffic.
  • Respect Pixabay's API terms: do not use the API to download and redistribute images in bulk or as a replacement for the Pixabay website.

Alternatives

Frequently asked questions

How do I store my Pixabay API key in Replit?

Click the lock icon πŸ”’ in the Replit sidebar to open the Secrets pane. Add a secret with the key PIXABAY_API_KEY and your Pixabay key as the value. Access it in Python with os.environ['PIXABAY_API_KEY'] and in Node.js with process.env.PIXABAY_API_KEY. Restart the Repl after adding the secret.

Is the Pixabay API free to use?

Yes. Pixabay provides free API access to all registered users with a limit of 100 requests per 60 seconds. There is no paid tier for the API itself, though creating a free Pixabay account is required to obtain an API key. Pixabay images are free to use under the Pixabay Content License for most commercial and personal use cases.

Can I search for videos with the Pixabay API?

Yes. Pixabay has a separate video endpoint at https://pixabay.com/api/videos/ that works with the same API key. Search parameters are similar to the image endpoint. The response includes video URLs in multiple resolutions (large, medium, small, tiny) along with duration, user, and tag metadata.

Does Pixabay require attribution for images used in my app?

The Pixabay Content License does not legally require attribution, but Pixabay strongly recommends crediting the photographer and linking to the Pixabay page as a courtesy. For commercial applications, always review the full Pixabay Content License at pixabay.com/service/license-summary/ to confirm your specific use case is covered.

Why does my Pixabay API search return a maximum of 500 results?

The Pixabay API limits pagination to 500 results maximum (totalHits is capped). This is a deliberate API limitation rather than a bug. The 'total' field in the raw response shows the real result count, but you can only retrieve results across the first 500. For broader searches, use more specific keywords or multiple smaller queries.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation β€” no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.