Quran PNG

A URL in, an image out. Any range of ayat as a transparent PNG, an SVG or a print-ready PDF of the actual printed muṣḥaf — no font to install, no shaping engine, no key.

Platforms
Anything that can make an HTTP GET
Time
About 7 minutes

What this is

Quran PNG is a tool, not one of the eight building blocks. It is a service built on the artwork that Quran SVG Elements publishes, and it exists to be the shortest possible path from a reference to a picture of that reference.

Reach for it when the destination cannot lay out Arabic text for you: Canva, Figma, Illustrator, Keynote, a PDF generator, an email template, a social card. Nothing in the response is typeset. Every word is vector artwork lifted from the printed plate and moved onto a new canvas.

Get an image now

curl -o kursi.png \
  "https://png.quran.ws/api/v1/image/2/255.png?layout=fit&aspect=wide&width=1400"

The same URL works as an <img> source. Access-Control-Allow-Origin: * is set, so a browser can fetch it directly.

<img
  src="https://png.quran.ws/api/v1/image/2/255.png?layout=fit&aspect=wide&width=1400"
  alt="Surah 2, ayah 255, from the printed Madani muṣḥaf"
/>

That is the whole API surface for the common case.

Try it live

Pick a surah, a range, a layout and an ink colour, and watch the URL and the live image change together.

Addressing an image

GET /api/v1/image/{surah}/{range}.{png|svg|pdf}

surah is 1–114. Anything outside that returns 400 with {"error":"surah must be 1..114"}.

range takes three forms:

FormExampleMeaning
A single ayah/2/255.pngAyah 255 only
A closed range/2/255-257.svgAyat 255 to 257
An open range/112/1-.pdfAyah 1 to the end of the surah

Ranges do not cross a surah boundary. A range beyond the end of the surah is rejected rather than clamped: /2/300.png returns 400 with {"error":"surah 2 has 286 ayahs, got 300-300"}.

There is a second, equivalent form for callers who would rather not build a path:

GET /api/v1/image?surah=112&from=1&to=4&format=svg

The format is taken from the extension, or from format= when there is no extension. png, svg and pdf are the only three; anything else returns 400.

One edition, one riwayah

Every image comes from the KFGQPC Madani muṣḥaf in the riwayah of Ḥafṣ — GET /api/v1/surahs reports "edition": "hafs-kfgqpc" and "print": "KFGQPC Madani mushaf, V4 1441H". There is no parameter to select another riwayah, so ayah numbers here are Kufan numbering throughout. If you need Warsh or Qālūn artwork, this is not the service; see Quran SVG.

The two layouts

Because the shapes are only ever moved, never scaled or stretched, there are two ways to lay a range out. layout=mushaf is the default.

mushaffit
What it doesReproduces the plate: every word keeps the x it has on the printed pageRepacks the same artwork, at the same size, into justified lines
Aspect ratioDetermined by the printed linesYou choose it with aspect
align, wordSpacing, justifyIgnored — the printed line has no alignment to chooseApply
Use it whenYou want fidelity to the pageYou want the ayah to fill a card, a story or a banner

Justification in fit moves the gaps only. The printed muṣḥaf stretches letters to justify a line, and doing that here would distort the artwork, so a line that would need more than three times its natural word spacing is left ragged instead.

aspect accepts the five named ratios or any explicit w:h:

NameRatio
square1:1
post4:5
story9:16
wide16:9
banner3:1
# a named ratio
curl -o story.png "https://png.quran.ws/api/v1/image/112/1-.png?layout=fit&aspect=story"

# an explicit one — anything matching w:h
curl -o odd.png "https://png.quran.ws/api/v1/image/112/1-.png?layout=fit&aspect=2.5:1"

Every parameter

Read from apps/api/params.mjs in the repository, which is the single place the service validates a query string.

ParameterValuesDefaultNotes
layoutmushaf · fitmushaf
aspectsquare · post · story · wide · banner · w:hsquarefit only
aligncenter · right · leftcenterfit only
justify0 to switch offonfit only
wordSpacing0.3 – 41Multiplier on the printed word gap; fit only
lineSpacing0.6 – 31Multiplier on the printed line height
width64 – 80002000Output pixel width; PNG only
colorAny hex, # optional#231f20The ink
backgroundAny hextransparentOmit it and you get alpha
padding0 – 40024Margin in artwork units, not pixels
basmalah0 to omitonOnly relevant to a range starting at ayah 1
vAny valueunpinnedChanges caching only — see below

Out-of-range values are rejected, not clamped, and the message names the parameter:

curl "https://png.quran.ws/api/v1/image/2/255.png?width=9000"
# {"error":"width must be between 64 and 8000, got 9000"}

0, false, no and off all read as false for justify and basmalah. Any other value is true.

The basmalah switch

For this service the basmalah rule is concrete, because it only ever serves Ḥafṣ:

بِسۡمِ ٱللَّهِ ٱلرَّحۡمَٰنِ ٱلرَّحِيمِ

1:1 · Ḥafṣ, from public/demo/fatiha.json

Pass basmalah=0 when you are composing a range into a design that already carries one.

Caching, and the v parameter

Renders are cached server-side and every response carries an ETag, so a conditional request costs you a 304.

curl -s -D - -o /dev/null "https://png.quran.ws/api/v1/image/2/255.png?v=3" | grep -i 'cache-control\|etag'
# cache-control: public, max-age=31536000, immutable
# etag: "hpOQJwwEfZQModXXT1FHhaLjcI4"

Without v, the response is cacheable but short-lived and revalidates, so a layout correction reaches you. With v, it is immutable for a year. Pin it when the image is embedded in something that must not change under you — a printed document, a published asset, a design file someone else owns.

v pins the cache, not the renderer

The service treats v as present-or-absent. Any value flips the response to immutable; it does not select a renderer version. ?v=3 and ?v=9 both return today's renderer — both respond with x-render-version: 3. So if the renderer is corrected, a URL you froze for a year keeps serving the old bytes from caches while a fresh fetch returns the new layout, and two readers see different images. Treat a pinned URL as a snapshot, and re-pin when x-render-version changes.

Response headers worth reading

HeaderExampleWhat it tells you
etag"iJn_wTYVArS4E8TyvsS-5VUynsc"Send it back as If-None-Match for a 304
x-render-version3The renderer that produced these bytes
x-quran-lines5How many lines the range laid out to
x-quran-words50How many words are in the image
content-dispositioninline; filename="quran-2-255.png"A sensible filename if the user saves it

x-quran-lines and x-quran-words are useful before you commit to a layout: the same range is 5 lines under layout=fit&aspect=wide and 6 lines under the plate, which is enough to change whether it fits your card.

Limits

You wantUse
The Qur'an as characters, searchable, with word numberingQuran Text
A complete printed page with a tappable ayah layerQuran SVG
The word and mark shapes themselves, to compose your own rendererQuran SVG Elements
The same pages rendered fast inside a mobile appQuran Engine

How this works

The service holds no font. It loads the word and mark shapes that Quran SVG Elements publishes — the same decomposition of the KFGQPC Madani plates, keyed surah:ayah:word, 77,432 words for Ḥafṣ — and a render collects the shapes in your range and translates them onto a new canvas; PNG is that SVG rasterised, PDF the same vector, page-sized. It runs as a live HTTP service at png.quran.ws, and the same picker also runs as a Canva side panel.