Guides / Reference
Dog Image API curl examples
By the Dog Image API team. Updated .
Every Dog Image API call works from a terminal with curl. Breed lists and previews need no key. Full-size PNGs and usage need an Authorization: Bearer header. This cookbook gives one short command per task, with the output you should expect, and ends with every error reply.
Set two variables once, so the commands below stay short.
BASE=https://dogimage.dev
export DOG_IMAGE_API_KEY="paste-your-key-here" # only needed from the full-size section on
List the breeds
curl -s "$BASE/api/v1/breeds" | head -c 300
The reply is JSON with a views list and a breeds list. No key is needed, and browsers on other sites may call this endpoint too.
Pipe it to jq
Count the breeds, without hardcoding a number anywhere:
curl -s "$BASE/api/v1/breeds" | jq '.breeds | length'
Print every slug, one per line:
curl -s "$BASE/api/v1/breeds" | jq -r '.breeds[].slug'
Find the breeds that come in more than one color, with how many variants each has:
curl -s "$BASE/api/v1/breeds" \
| jq -r '.breeds[] | select(.variants | length > 1) | "\(.slug) \(.variants | length)"'
On the day of writing this prints seven breeds, from french-bulldog to great-dane. List the nine view ids:
curl -s "$BASE/api/v1/breeds" | jq -r '.views[].id'
Print the crossbreeds only:
curl -s "$BASE/api/v1/breeds" | jq -r '.breeds[] | select(.crossbreed) | .name'
Look at one breed
curl -s "$BASE/api/v1/breeds/pug" | jq '{name, default_variant, summary: .summary.title}'
The reply carries a summary (which may be null), and for each variant a views object with preview_512, preview_1024 and full links. Pull out the colors of a breed and the link to one full-size file:
curl -s "$BASE/api/v1/breeds/golden-retriever" | jq -r '.variants[].slug'
curl -s "$BASE/api/v1/breeds/pug" | jq -r '.variants[0].views.head.full'
The full link is a pointer to the full-size endpoint. Opening it still needs your key.
Download a free preview
The preview endpoint redirects. Without -L, curl shows the redirect and stops.
curl -s -i "$BASE/api/v1/images/pug/default/front?size=512" | head -n 3
You see HTTP/2 302 and a location: line that points at a .webp file. With -L, curl follows it:
curl -sSL "$BASE/api/v1/images/pug/default/front?size=512" -o pug-front-512.webp
file pug-front-512.webp
Sizes are 512 and 1024, and 1024 is the default. A preview is a transparent WebP, and showing one on a page requires the credit link from the license.
Download a full-size PNG
curl -sS --fail-with-body \
-H "Authorization: Bearer $DOG_IMAGE_API_KEY" \
"$BASE/api/v1/images/pug/default/front?size=full" \
-o pug-front.png
The file is a 2048 x 2048 transparent PNG, about 1 to 7 MB. --fail-with-body makes curl exit with an error code on a 4xx or 5xx, so your shell script can tell success from failure.
Download all nine views of one breed, using the view ids from the breeds list:
for view in $(curl -s "$BASE/api/v1/breeds" | jq -r '.views[].id'); do
curl -sS --fail-with-body \
-H "Authorization: Bearer $DOG_IMAGE_API_KEY" \
"$BASE/api/v1/images/beagle/default/$view?size=full" \
-o "beagle-$view.png" || break
done
The || break stops the loop on the first failure, such as a 429, instead of saving eight more error bodies.
Check usage
curl -s -H "Authorization: Bearer $DOG_IMAGE_API_KEY" "$BASE/api/v1/usage" | jq
{ "month": "2026-11", "plan": "starter", "limit": 200, "used": 12, "remaining": 188 }
That sample is the documented shape. On the All images plan, limit and remaining are null.
Read the response headers
-D - writes the headers to the terminal, and -o keeps the binary body out of the way:
curl -sS -D - -o pug-front.png \
-H "Authorization: Bearer $DOG_IMAGE_API_KEY" \
"$BASE/api/v1/images/pug/default/front?size=full"
A good reply includes Content-Type: image/png, a Content-Disposition header with a file name such as pug-fawn-front.png, and X-Quota-Limit, X-Quota-Used and X-Quota-Remaining. On the All images plan the quota values read unlimited.
To keep only the quota lines, write the headers to a file and filter it:
curl -sS -D headers.txt -o pug-front.png \
-H "Authorization: Bearer $DOG_IMAGE_API_KEY" \
"$BASE/api/v1/images/pug/default/front?size=full"
grep -i '^x-quota' headers.txt
To get only the status code of a call, use -w:
curl -s -o /dev/null -w '%{http_code}\n' "$BASE/api/v1/images/pug/default/front?size=512"
That prints 302, because -L was not set.
See every error
Errors are JSON in the shape {"error": {"code": "...", "message": "..."}}. These three you can reproduce right now with no key:
curl -s "$BASE/api/v1/images/pug/default/front?size=99"
{"error":{"code":"bad_size","message":"size must be one of 512, 1024, full.","choices":["512","1024","full"]}}
curl -s "$BASE/api/v1/images/pug/default/front?size=full"
{"error":{"code":"missing_or_invalid_key","message":"Full-size files need an API key: Authorization: Bearer <key>."}}
curl -s "$BASE/api/v1/images/nope/default/front"
{"error":{"code":"unknown_breed","message":"No breed \"nope\". GET /api/v1/breeds lists them."}}
The 404 family also includes unknown_variant and unknown_view, and on the image endpoint each lists the valid choices in the reply. The breed detail endpoint uses the same JSON error:
curl -s -w '\n%{http_code}\n' "$BASE/api/v1/breeds/nope"
{"error":{"code":"unknown_breed","message":"No breed \"nope\". GET /api/v1/breeds lists them."}}
404
The other codes need an account state you will meet in real use:
| Status | Code | Meaning |
|---|---|---|
| 402 | no_active_plan |
The key is valid but has no active plan |
| 429 | quota_used_up |
The monthly full-size count is spent |
| 502 | file_unavailable |
Not counted. Try again |
| 503 | plan_check_failed |
Try again |
Pick a retry policy in the errors and quotas reference. The docs list every endpoint.
Questions
How do I make curl follow the preview redirect?
Add -L. The preview endpoint answers with a 302 to a WebP file, and -L makes curl fetch the file itself. Add -o to name the output.
How do I see the quota headers with curl?
Use -D - to print the response headers, with -o to send the image body to a file. Look for X-Quota-Limit, X-Quota-Used and X-Quota-Remaining.
Why does curl save a small JSON file instead of my PNG?
The request failed and the error body was saved under your file name. Add --fail-with-body so curl returns a non-zero exit code and still prints the JSON error.
Is the preview image safe to use in a project?
Previews are free with a visible credit link next to the image or on the same page. They are AI-generated illustrations, not photos.
Next steps
- API docs: endpoints, keys, limits and errors.
- All dog breeds, each with nine views.
- Pricing for full-size transparent PNG files.
- A list of dog breeds as JSON
- AI-generated dog breed images: what to know first
- Dog drawing reference: one dog from nine angles
- Dog front view and rear view reference images