Skip to content

Character Data

Enables the retrieval of single characters or filtered collections of characters. Eg; Character profiles, reports, and performance data

Overview

  • Coverage: 5 endpoints implemented
  • Use Cases: Character analysis, performance tracking, report history, ranking comparison
  • Rate Limit Impact: 2-5 points per request (varies by complexity)

Methods

get_character_by_id()

Purpose: Retrieve detailed character profile information

ParametersTypeRequiredDescription
idintYesThe character ID to retrieve

Returns: GetCharacterById object with the following structure:

FieldTypeDescription
character_data.character.idintCharacter ID
character_data.character.namestrCharacter name
character_data.character.class_idintCharacter class ID
character_data.character.race_idintCharacter race ID
character_data.character.guild_rankintGuild rank (0 if not in guild)
character_data.character.hiddenboolWhether character profile is hidden
character_data.character.server.namestrServer name
character_data.character.server.region.namestrServer region name

Example:

import asyncio
from esologs.client import Client
from esologs.auth import get_access_token

async def get_character_profile():
    token = get_access_token()
    async with Client(
        url="https://www.esologs.com/api/v2/client",
        headers={"Authorization": f"Bearer {token}"}
    ) as client:

        character = await client.get_character_by_id(id=314050)

        if character.character_data and character.character_data.character:
            char = character.character_data.character
            print(f"Character: {char.name} (ID: {char.id})")
            print(f"Class ID: {char.class_id}, Race ID: {char.race_id}")
            print(f"Server: {char.server.name} ({char.server.region.name})")
            print(f"Guild Rank: {char.guild_rank}")

asyncio.run(get_character_profile())

Output:

Character: Zalduk Nightsky (ID: 314050)
Class ID: 1, Race ID: 5
Server: Megaserver (Europe)
Guild Rank: 0

get_character_reports()

Purpose: Get recent reports for a specific character

ParametersTypeRequiredDescription
character_idintYesThe character ID to get reports for
limitintNoNumber of reports to return (default: 10)

Returns: GetCharacterReports object with the following structure:

FieldTypeDescription
character_data.character.recent_reports.dataList[Report]List of report objects
character_data.character.recent_reports.totalintTotal number of reports
character_data.character.recent_reports.per_pageintReports per page
character_data.character.recent_reports.current_pageintCurrent page number
character_data.character.recent_reports.from_int | NoneStarting record number
character_data.character.recent_reports.toint | NoneEnding record number
character_data.character.recent_reports.last_pageintLast page number
character_data.character.recent_reports.has_more_pagesboolWhether more pages exist

Report Object Fields:

FieldTypeDescription
codestrUnique report code
start_timefloatReport start timestamp
end_timefloatReport end timestamp
zone.namestrZone name where report was recorded

Example:

import asyncio
from esologs.client import Client
from esologs.auth import get_access_token

async def get_character_recent_reports():
    token = get_access_token()
    async with Client(
        url="https://www.esologs.com/api/v2/client",
        headers={"Authorization": f"Bearer {token}"}
    ) as client:

        reports = await client.get_character_reports(character_id=314050, limit=5)

        if reports.character_data and reports.character_data.character:
            recent_reports = reports.character_data.character.recent_reports
            if recent_reports:
                print(f"Total reports: {recent_reports.total}")
                print(f"Showing {len(recent_reports.data)} reports:")

                for report in recent_reports.data:
                    if report:
                        zone_name = report.zone.name if report.zone else "Unknown Zone"
                        print(f"- {report.code} in {zone_name}")

asyncio.run(get_character_recent_reports())

Output:

Total reports: 286
Showing 5 reports:
- f2QKpYZdwTVGMq4R in Rockgrove
- 7D2qyThHzv1wMdkQ in Aetherian Archive

get_character_encounter_ranking()

Purpose: Get character's ranking for a specific encounter

ParametersTypeRequiredDescription
character_idintYesThe character ID
encounter_idintYesThe encounter ID to get rankings for

Returns: GetCharacterEncounterRanking object with the following structure:

FieldTypeDescription
character_data.character.encounter_rankingsAnyRankings data (structure varies by encounter)

Example:

import asyncio
from esologs.client import Client
from esologs.auth import get_access_token

async def get_character_encounter_ranking():
    token = get_access_token()
    async with Client(
        url="https://www.esologs.com/api/v2/client",
        headers={"Authorization": f"Bearer {token}"}
    ) as client:

        ranking = await client.get_character_encounter_ranking(
            character_id=314050,
            encounter_id=63  # Rockgrove encounter
        )

        if ranking.character_data and ranking.character_data.character:
            rankings = ranking.character_data.character.encounter_rankings
            if rankings:
                print("Character has rankings for this encounter")
                print(f"Available data: {list(rankings.keys())[:5]}")
            else:
                print("No rankings found for this encounter")

asyncio.run(get_character_encounter_ranking())

Output:

Character has rankings for this encounter
Available data: ['bestAmount', 'medianPerformance', 'averagePerformance', 'totalKills', 'fastestKill']

get_character_encounter_rankings()

Purpose: Get character's rankings for a specific encounter with filtering options

ParametersTypeRequiredDescription
character_idintYesThe character ID
encounter_idintYesThe encounter ID to get rankings for
by_bracketboolNoGroup rankings by bracket
class_namestrNoFilter by class name
compareRankingCompareTypeNoComparison type for rankings
difficultyintNoDifficulty level filter
include_combatant_infoboolNoInclude combatant information
include_private_logsboolNoInclude private logs in rankings
metricCharacterRankingMetricTypeNoRanking metric type
partitionintNoPartition number
roleRoleTypeNoRole filter (Tank, Healer, DPS)
sizeintNoNumber of results to return
spec_namestrNoSpecialization name filter
timeframeRankingTimeframeTypeNoTime period for rankings

Returns: GetCharacterEncounterRankings object with the following structure:

FieldTypeDescription
character_data.character.encounter_rankingsAnyDetailed rankings data with filters applied

Example:

import asyncio
from esologs.client import Client
from esologs.auth import get_access_token

async def get_character_encounter_rankings():
    token = get_access_token()
    async with Client(
        url="https://www.esologs.com/api/v2/client",
        headers={"Authorization": f"Bearer {token}"}
    ) as client:

        rankings = await client.get_character_encounter_rankings(
            character_id=314050,
            encounter_id=63,  # Rockgrove encounter
            include_combatant_info=True
        )

        if rankings.character_data and rankings.character_data.character:
            encounter_rankings = rankings.character_data.character.encounter_rankings
            if encounter_rankings:
                print("Character has detailed encounter rankings")
                print(f"Best score: {encounter_rankings.get('bestAmount', 0)}")
                print(f"Total kills: {encounter_rankings.get('totalKills', 0)}")
                print(f"Number of ranks: {len(encounter_rankings.get('ranks', []))}")
                if encounter_rankings.get('ranks'):
                    first_rank = encounter_rankings['ranks'][0]
                    print(f"Latest performance: {first_rank.get('amount', 0)} points")
                    print(f"Rank percentile: {first_rank.get('rankPercent', 0):.1f}%")
            else:
                print("No detailed rankings found")

asyncio.run(get_character_encounter_rankings())

Output:

Character has detailed encounter rankings
Best score: 296773
Total kills: 11
Number of ranks: 11
Latest performance: 296773 points
Rank percentile: 68.0%

get_character_zone_rankings()

Purpose: Get character's rankings for a specific zone with filtering options

ParametersTypeRequiredDescription
character_idintYesThe character ID
zone_idintNoThe zone ID to get rankings for
by_bracketboolNoGroup rankings by bracket
class_namestrNoFilter by class name
compareRankingCompareTypeNoComparison type for rankings
difficultyintNoDifficulty level filter
include_private_logsboolNoInclude private logs in rankings
metricCharacterRankingMetricTypeNoRanking metric type
partitionintNoPartition number
roleRoleTypeNoRole filter (Tank, Healer, DPS)
sizeintNoNumber of results to return
spec_namestrNoSpecialization name filter
timeframeRankingTimeframeTypeNoTime period for rankings

Returns: GetCharacterZoneRankings object with the following structure:

FieldTypeDescription
character_data.character.zone_rankingsAnyZone-specific rankings data with filters applied

Example:

import asyncio
from esologs.client import Client
from esologs.auth import get_access_token

async def get_character_zone_rankings():
    token = get_access_token()
    async with Client(
        url="https://www.esologs.com/api/v2/client",
        headers={"Authorization": f"Bearer {token}"}
    ) as client:

        rankings = await client.get_character_zone_rankings(
            character_id=314050,
            zone_id=19,  # Ossein Cage zone
            size=5
        )

        if rankings.character_data and rankings.character_data.character:
            zone_rankings = rankings.character_data.character.zone_rankings
            if zone_rankings:
                print("Character has zone rankings")
                print(f"Available metrics: {list(zone_rankings.keys())[:3]}")
            else:
                print("No zone rankings found")

asyncio.run(get_character_zone_rankings())

Output:

Character has zone rankings
Available metrics: ['bestPerformanceAverage', 'medianPerformanceAverage', 'difficulty']

Common Usage Patterns

Character Profile Analysis

import asyncio
from esologs.client import Client
from esologs.auth import get_access_token

async def analyze_character(character_id: int):
    """Complete character analysis including profile and recent activity."""
    token = get_access_token()
    async with Client(
        url="https://www.esologs.com/api/v2/client",
        headers={"Authorization": f"Bearer {token}"}
    ) as client:

        # Get character profile
        character = await client.get_character_by_id(id=character_id)

        if character.character_data and character.character_data.character:
            char = character.character_data.character
            print(f"Analyzing: {char.name}")
            print(f"Server: {char.server.name} ({char.server.region.name})")

            # Get recent reports
            reports = await client.get_character_reports(character_id=character_id)
            if reports.character_data and reports.character_data.character:
                recent_reports = reports.character_data.character.recent_reports
                if recent_reports:
                    print(f"Recent activity: {recent_reports.total} reports")

# Run the analysis
asyncio.run(analyze_character(314050))

Output:

Analyzing: Zalduk Nightsky
Server: Megaserver (Europe)
Recent activity: 286 reports

Performance Tracking

import asyncio
from esologs.client import Client
from esologs.auth import get_access_token

async def track_character_performance(character_id: int, encounter_id: int):
    """Track character performance for a specific encounter."""
    token = get_access_token()
    async with Client(
        url="https://www.esologs.com/api/v2/client",
        headers={"Authorization": f"Bearer {token}"}
    ) as client:

        # Get encounter rankings
        rankings = await client.get_character_encounter_rankings(
            character_id=character_id,
            encounter_id=encounter_id,
            include_combatant_info=True
        )

        if rankings.character_data and rankings.character_data.character:
            encounter_rankings = rankings.character_data.character.encounter_rankings
            if encounter_rankings:
                print("Performance data available for analysis")
                print(f"Best score: {encounter_rankings.get('bestAmount', 0)}")
                print(f"Total kills: {encounter_rankings.get('totalKills', 0)}")
                print(f"Difficulty: {encounter_rankings.get('difficulty', 'Unknown')}")
                ranks = encounter_rankings.get('ranks', [])
                print(f"Number of ranking entries: {len(ranks)}")

                if ranks:
                    # Show recent performance trend
                    recent_scores = [rank.get('amount', 0) for rank in ranks[:3]]
                    print(f"Recent scores: {recent_scores}")
                    avg_recent = sum(recent_scores) / len(recent_scores) if recent_scores else 0
                    print(f"Average recent performance: {avg_recent:.0f}")
            else:
                print("No performance data found for this encounter")

# Run the performance tracking
asyncio.run(track_character_performance(314050, 63))

Output:

Performance data available for analysis
Best score: 296773
Total kills: 11
Difficulty: 122
Number of ranking entries: 11
Recent scores: [296773, 295705, 294120]
Average recent performance: 295533

Error Handling

from esologs.exceptions import GraphQLClientHttpError, GraphQLClientGraphQLMultiError
from pydantic import ValidationError

try:
    character = await client.get_character_by_id(id=999999)  # Non-existent ID
except GraphQLClientGraphQLMultiError as e:
    print(f"GraphQL error: {e}")
except ValidationError as e:
    print(f"Invalid parameters: {e}")
except GraphQLClientHttpError as e:
    if e.status_code == 429:
        print("Rate limit exceeded")
    elif e.status_code == 404:
        print("Character not found")

Rate Limiting Notes

  • Character profile requests: 2-3 points
  • Character reports: 3-4 points
  • Character rankings: 4-5 points
  • Add delays between requests: await asyncio.sleep(0.2)
  • Monitor rate limits using get_rate_limit_data()