Prerequisites
You need three things:
- Python 3.8 or newer.
- The
requestslibrary. - A free API Ninjas API key — issued instantly, no credit card. If you already have an account, it's on your profile page.
pip install requestsStep 1: Generate your first QR code
The endpoint is /v1/qrcode. Pass the text to encode as data and ask for format=png. Unlike most endpoints, the response is not JSON — the body is the PNG itself, so write response.content in binary mode:
import requests
response = requests.get(
'https://api.api-ninjas.com/v1/qrcode',
params={'data': 'https://api-ninjas.com', 'format': 'png'},
headers={'X-Api-Key': 'YOUR_API_KEY'},
timeout=10,
)
response.raise_for_status()
with open('qr.png', 'wb') as f:
f.write(response.content)
print(f'Wrote qr.png ({len(response.content)} bytes)')Open qr.png and scan it with your phone — it resolves to the encoded URL. The two habits that matter: always 'wb' when writing, and never response.json() on an image response.
Step 2: Set size and colors
Three optional parameters control the output:
| Parameter | Default | Meaning |
|---|---|---|
size | 256 | Image width/height in pixels. Use 512+ for print. |
fg_color | 000000 | Module color — 6-digit hex, no leading #. |
bg_color | ffffff | Background color — 6-digit hex, no leading #. |
Wrapped as a function with the key in an environment variable and a shared session, the client looks like this:
import os
import requests
API_URL = 'https://api.api-ninjas.com/v1/qrcode'
session = requests.Session()
session.headers['X-Api-Key'] = os.environ.get('API_NINJAS_KEY', 'YOUR_API_KEY')
def generate_qr(
data: str,
output: str,
size: int = 256,
fg: str = '000000',
bg: str = 'ffffff',
) -> None:
"""Generate a QR code PNG and write it to the output path."""
response = session.get(
API_URL,
params={'data': data, 'format': 'png', 'size': size,
'fg_color': fg, 'bg_color': bg},
timeout=10,
)
response.raise_for_status()
with open(output, 'wb') as f:
f.write(response.content)
generate_qr('https://api-ninjas.com', 'site.png', size=512)
print('Wrote site.png')Brand colors work as long as you keep contrast high — scanners need it:
# Brand-colored: blue modules on a light-gray background
generate_qr(
'https://api-ninjas.com',
'brand.png',
size=512,
fg='1664ea',
bg='f6f9fc',
)Step 3: Encode real payloads
A QR code encodes arbitrary text, and phones treat certain formats specially. A vCard block becomes an “add contact” prompt:
vcard = '''BEGIN:VCARD
VERSION:3.0
FN:Jane Doe
ORG:Acme Inc.
TEL:+1-555-0100
EMAIL:jane@example.com
END:VCARD'''
generate_qr(vcard, 'jane-vcard.png', size=512)And a WIFI: string joins the network on scan — the classic guest-Wi-Fi poster:
# Scanning this joins the guest Wi-Fi automatically
wifi = 'WIFI:T:WPA;S:GuestNetwork;P:correcthorsebatterystaple;;'
generate_qr(wifi, 'guest-wifi.png')Step 4: Generate in bulk
Table tents, event badges, per-page posters — bulk generation is a loop over payloads, one file per code:
urls = {
'home': 'https://api-ninjas.com',
'pricing': 'https://api-ninjas.com/pricing',
'docs': 'https://api-ninjas.com/api',
}
for name, url in urls.items():
generate_qr(url, f'{name}.png')
print(f'Wrote {name}.png')Step 5: Handle errors
The failure modes are simple: empty data (400), a missing key (401), and rate limits on big batches (429):
from requests.exceptions import HTTPError, RequestException
try:
generate_qr('', 'empty.png') # empty data is rejected
except HTTPError as error:
status = error.response.status_code
if status == 400:
print('Bad request — data must not be empty')
elif status == 401:
print('Missing or invalid API key')
elif status == 429:
print('Rate limit exceeded — slow the batch down')
else:
print(f'HTTP {status}: {error.response.text}')
except RequestException as error:
print(f'Network error: {error}')Where to go from here
For retail-style linear barcodes, the Barcode API follows the same request-and-save pattern. The complete script — payload and output file as command-line arguments — is below.