When to use this API
When you need a dad joke — a random one, a specific one by ID, or jokes matching a search term. This is the canonical dad joke API: 744 jokes, zero auth, one Accept header away from JSON. It's surprisingly useful as a lightweight "hello world" call in chat bots and icebreaker flows, and the search endpoint is the only programmatic way to find a joke about a specific topic in a curated, family-safe collection. For joke categories beyond dad-style puns (dark humor, programming jokes, one-liners), look elsewhere — this API is single-genre by design.
Fetching a random dad joke
"Tell me a joke." The root endpoint returns a random joke with no parameters. Set the Accept header to application/json — without it, you get plain text and lose the joke ID.
curl -H "Accept: application/json" "https://icanhazdadjoke.com/" | head -c 10000
{
"id": "diGeqOfiqc",
"joke": "What's E.T. short for? He's only got little legs.",
"status": 200
}
The id field is a short alphanumeric string — persistent, shareable, and the key to the /j/{joke_id} endpoint. The status field mirrors the HTTP status code and is always 200 on success; it's redundant but convenient if you're parsing the body without checking HTTP headers. This particular joke is a good example of the genre's density: it works on two levels (the abbreviation "E.T." and the literal reading of "short") in under ten words, which is about the tightest construction you'll find in the 744-joke corpus.
What's E.T. short for? He's only got little legs.
Looking up a specific joke by ID
"I saw a joke about a poultry-geist — find it for me." If you have a joke ID (from a previous random fetch, a search result, or someone sharing a permalink), /j/{joke_id} retrieves that exact joke. No pagination, no search — just one joke.
curl -H "Accept: application/json" "https://icanhazdadjoke.com/j/HYTfVf21ob" | head -c 10000
{
"id": "HYTfVf21ob",
"joke": "What do you get if you cross a turkey with a ghost? A poultry-geist!",
"status": 200
}
The response shape is identical to the random endpoint — same three fields, same structure. Joke IDs are stable: the same ID always returns the same joke. The API returns 404 with a JSON body { "status": 404, "message": "Joke not found" } for invalid IDs, which is cleaner than most joke APIs that silently return a random joke on miss. This makes /j/{joke_id} safe for bookmarking or deep-linking.
What do you get if you cross a turkey with a ghost? A poultry-geist!
Searching for jokes by keyword
"Find me a joke about cats." The search endpoint filters the corpus by term and paginates the results. Always set limit — the default is 20, which is manageable, but combining it with a term keeps the response tight.
curl -H "Accept: application/json" "https://icanhazdadjoke.com/search?term=cat&limit=5" | head -c 10000
{
"current_page": 1,
"limit": 5,
"next_page": 2,
"previous_page": 1,
"results": [
{ "id": "0DdaxAX0orc", "joke": "I accidentally took my cats meds last night. Don't ask meow." },
{ "id": "B4fFKqf9ld", "joke": "What do you call a pile of cats? A meow-ntain." }
],
"search_term": "cat",
"status": 200,
"total_jokes": 3,
"total_pages": 1
}
The real story here is the pagination metadata: total_jokes tells you how many matches exist before you paginate, and total_pages tells you how many pages at your current limit. An empty search term returns the entire 744-joke corpus paginated — that's the firehose, and it's the fastest way to tank your context window. The previous_page value is 1 on the first page (not 0 or null), which is an unusual convention — page numbers are 1-indexed and the API never signals "no previous page" with a null. Also note the search is case-insensitive and matches substrings: "cat" matches "cats", "category", and "scattered".
I accidentally took my cats meds last night. Don't ask meow.
Pitfalls
- Omit the
Accept: application/jsonheader and you get plain text. The API defaults totext/plain— a raw joke string with no ID, no JSON structure. This is by design (the API started as a Slack-friendly text endpoint), but it's a trap if you're parsing JSON. - Empty search term returns all 744 jokes. Calling
/searchwithouttermor with an emptytermparameter dumps the entire corpus paginated. Always set atermunless you genuinely want the full collection. previous_pageis1, notnull, on page 1. The API uses 1-indexed pages and never nulls out the previous-page pointer. Checkcurrent_pageinstead of testingprevious_pagefor nullity.
One-line summary for the user
I can pull a random dad joke, look one up by ID, or search the 744-joke corpus by keyword from icanhazdadjoke.com — no auth required, just set the Accept header to JSON.