Practice: PokeAPI

About PokeAPI

Free Pokemon API. No authentication required. Great for learning.

Perfect for practicing:

  • Nested data traversal

  • Following URL references

  • Complex jq filters

  • Caching strategies

Basic Requests

Get a Pokemon

# By name
curl -s https://pokeapi.co/api/v2/pokemon/pikachu | jq

# By ID
curl -s https://pokeapi.co/api/v2/pokemon/25 | jq

# Just the basics
curl -s https://pokeapi.co/api/v2/pokemon/pikachu | jq '{name, id, height, weight}'

Pokemon Stats

# Get stats
curl -s https://pokeapi.co/api/v2/pokemon/charizard | jq '.stats[] | {stat: .stat.name, value: .base_stat}'

# Total base stats
curl -s https://pokeapi.co/api/v2/pokemon/charizard | jq '[.stats[].base_stat] | add'

Types

# Pokemon's types
curl -s https://pokeapi.co/api/v2/pokemon/bulbasaur | jq '.types[].type.name'

# All fire type Pokemon (paginated)
curl -s https://pokeapi.co/api/v2/type/fire | jq '.pokemon[:10] | .[].pokemon.name'

Abilities

# Pokemon's abilities
curl -s https://pokeapi.co/api/v2/pokemon/eevee | jq '.abilities[] | {ability: .ability.name, hidden: .is_hidden}'

# Ability details
curl -s https://pokeapi.co/api/v2/ability/intimidate | jq '{name, effect: .effect_entries[] | select(.language.name == "en") | .effect}'

Resource Lists

Paginated Lists

# List Pokemon (paginated)
curl -s "https://pokeapi.co/api/v2/pokemon?limit=10&offset=0" | jq '.results[].name'

# Count total
curl -s https://pokeapi.co/api/v2/pokemon | jq '.count'

# Next/previous pages
curl -s https://pokeapi.co/api/v2/pokemon | jq '{count, next, previous}'

Other Resources

# Generations
curl -s https://pokeapi.co/api/v2/generation | jq '.results[].name'

# Moves
curl -s "https://pokeapi.co/api/v2/move?limit=10" | jq '.results[].name'

# Items
curl -s "https://pokeapi.co/api/v2/item?limit=10" | jq '.results[].name'

Following References

PokeAPI returns URLs to related resources. You need to follow them:

# Get Pokemon's species URL
species_url=$(curl -s https://pokeapi.co/api/v2/pokemon/pikachu | jq -r '.species.url')

# Follow it
curl -s "$species_url" | jq '{name, generation: .generation.name, habitat: .habitat.name}'

Evolution Chain

# Get evolution chain (multi-step)
# 1. Get Pokemon
# 2. Get species
# 3. Get evolution chain

pokemon="eevee"

# Step through
species_url=$(curl -s "https://pokeapi.co/api/v2/pokemon/$pokemon" | jq -r '.species.url')
evo_url=$(curl -s "$species_url" | jq -r '.evolution_chain.url')
curl -s "$evo_url" | jq '.chain.evolves_to[].species.name'

Complex Queries

Pokemon Card

# Build a "Pokemon card" summary
pokemon_card() {
  local pokemon="$1"
  local data
  data=$(curl -s "https://pokeapi.co/api/v2/pokemon/$pokemon")

  echo "=== $(echo "$data" | jq -r '.name | ascii_upcase') ==="
  echo "ID: $(echo "$data" | jq -r '.id')"
  echo "Types: $(echo "$data" | jq -r '[.types[].type.name] | join(", ")')"
  echo "Height: $(echo "$data" | jq -r '.height / 10')m"
  echo "Weight: $(echo "$data" | jq -r '.weight / 10')kg"
  echo ""
  echo "Base Stats:"
  echo "$data" | jq -r '.stats[] | "  \(.stat.name): \(.base_stat)"'
  echo ""
  echo "Abilities:"
  echo "$data" | jq -r '.abilities[] | "  \(.ability.name)\(if .is_hidden then " (hidden)" else "" end)"'
}

pokemon_card charizard

Type Effectiveness

# Get type strengths/weaknesses
curl -s https://pokeapi.co/api/v2/type/fire | jq '{
  name,
  double_damage_to: [.damage_relations.double_damage_to[].name],
  half_damage_to: [.damage_relations.half_damage_to[].name],
  no_damage_to: [.damage_relations.no_damage_to[].name],
  double_damage_from: [.damage_relations.double_damage_from[].name],
  half_damage_from: [.damage_relations.half_damage_from[].name],
  no_damage_from: [.damage_relations.no_damage_from[].name]
}'

Move Details

# Get move info
curl -s https://pokeapi.co/api/v2/move/thunderbolt | jq '{
  name,
  type: .type.name,
  power,
  accuracy,
  pp,
  damage_class: .damage_class.name,
  effect: (.effect_entries[] | select(.language.name == "en") | .short_effect)
}'

Caching Example

PokeAPI data doesn’t change often. Cache it:

poke_cached() {
  local endpoint="$1"
  local cache_dir="/tmp/pokeapi_cache"
  local cache_file="$cache_dir/$(echo "$endpoint" | md5sum | cut -d' ' -f1).json"

  mkdir -p "$cache_dir"

  if [[ -f "$cache_file" ]]; then
    cat "$cache_file"
  else
    curl -s "https://pokeapi.co/api/v2/$endpoint" | tee "$cache_file"
  fi
}

# Usage (instant after first call)
poke_cached pokemon/pikachu | jq '.name'

Shell Function

poke() {
  local cmd="${1:-help}"
  shift

  case "$cmd" in
    pokemon|p)
      curl -s "https://pokeapi.co/api/v2/pokemon/$1" | jq "${2:-.}"
      ;;
    type|t)
      curl -s "https://pokeapi.co/api/v2/type/$1" | jq "${2:-.}"
      ;;
    move|m)
      curl -s "https://pokeapi.co/api/v2/move/$1" | jq "${2:-.}"
      ;;
    ability|a)
      curl -s "https://pokeapi.co/api/v2/ability/$1" | jq "${2:-.}"
      ;;
    list)
      curl -s "https://pokeapi.co/api/v2/$1?limit=${2:-20}" | jq '.results[].name' -r
      ;;
    random)
      local id=$((RANDOM % 898 + 1))
      curl -s "https://pokeapi.co/api/v2/pokemon/$id" | jq '{id, name, types: [.types[].type.name]}'
      ;;
    *)
      echo "Usage: poke {pokemon|type|move|ability|list|random} [name/id] [jq filter]"
      echo "Examples:"
      echo "  poke pokemon pikachu"
      echo "  poke type fire '.pokemon[:5]'"
      echo "  poke move thunderbolt"
      echo "  poke list pokemon 50"
      echo "  poke random"
      ;;
  esac
}

Challenges

Challenge 1: Team Builder

# Get a random team of 6 Pokemon
for i in {1..6}; do
  id=$((RANDOM % 898 + 1))
  curl -s "https://pokeapi.co/api/v2/pokemon/$id" | jq -r '"\(.name) (\([.types[].type.name] | join("/")))"'
  sleep 0.3
done

Challenge 2: Strongest by Stat

# Find Pokemon with highest attack (first 100)
for id in $(seq 1 100); do
  curl -s "https://pokeapi.co/api/v2/pokemon/$id" 2>/dev/null | jq -r '"\(.stats[] | select(.stat.name == "attack") | .base_stat) \(.name)"'
  sleep 0.2
done | sort -rn | head -10

Challenge 3: Type Coverage

# What types does this Pokemon's moves cover?
pokemon="charizard"
curl -s "https://pokeapi.co/api/v2/pokemon/$pokemon" | jq '[.moves[].move.name][:10]' | while read -r move; do
  move=$(echo "$move" | tr -d '",')
  [[ -z "$move" || "$move" == "[" || "$move" == "]" ]] && continue
  curl -s "https://pokeapi.co/api/v2/move/$move" 2>/dev/null | jq -r '.type.name' 2>/dev/null
done | sort -u

Exercises Checklist

  • Get Pikachu’s base stats total

  • List all fire-type Pokemon names

  • Find Eevee’s evolution options

  • Get the effect text for the move "Earthquake"

  • Build a "Pokemon card" function showing key info

  • Find which types fire is super effective against

  • Create a cached version of your Pokemon function

  • Generate a random team of 6 Pokemon