For developers

For application developers

Using the HamQTH API? Please tell your users. HamQTH and its API are free: no fees, no keys to buy. All we ask in return: if your application, website or device uses data from HamQTH (callbook, DXCC, spots, logbook...), say so somewhere your users can see it, e.g. "Data provided by HamQTH.com", and invite them to register on HamQTH and keep their profile up to date. The callbook is only as good as the profiles in it: every registered and maintained profile makes the data your application gets back more accurate, for you and for everyone else.

API v2 is the current HamQTH API. It replaces the original API (the v1 tab), which keeps working for existing applications. This page is the guide; the reference is the interactive API reference (Swagger UI, try any endpoint there) and its OpenAPI document (/api/v2/openapi.json), from which you can generate a client for your language. All v2 endpoints share these rules:

  • URLs start with https://www.hamqth.com/api/v2/. Use HTTPS.
  • Answers are JSON by default, XML with format=xml. Both have the same structure.
  • Lists are arrays (never objects keyed by a callsign), numbers are numbers (14025.3, not "14 025.3"), times are UTC in ISO 8601 (2026-10-03T07:58:00Z), a missing value is null.
  • List parameters are comma separated, e.g. bands=20M,40M. Upper or lower case, spaces around commas are fine.
  • Errors use HTTP status codes with a JSON body saying what is wrong (see Errors). An invalid parameter is 422.
  • Endpoints marked login need a token from Login in the Authorization header. The password goes only to the login, in a POST body, never in a URL.
  • Every endpoint can be called from any web page (Access-Control-Allow-Origin: *).
LoginPOST /api/v2/logina token for the endpoints marked login
Callbook lookupGET /api/v2/callbook/{callsign}login; v1: xml.php, xml_bio.php, xml_latlong.php, adif.php
Recent activityGET /api/v2/callbook/{callsign}/activitylogin; v1: xml_recactivity.php
DXCCGET /api/v2/dxccv1: dxcc.php, dxcc_json.php
DX cluster spotsGET /api/v2/spotsv1: dxc_csv.php, dxc_json.php
RBN spotsGET /api/v2/rbnv1: rbn_data.php
QSO verificationGET /api/v2/verifyv1: verifyqso.php
Log uploadPOST /api/v2/log/uploadslogin; v1: prg_log_upload.php
Real-time QSOPOST / PUT / DELETE /api/v2/log/qsologin; v1: qso_realtime.php
Solar dataGET /api/v2/solarnew in v2

Login

Send the HamQTH callsign and password as JSON (or as form fields) in a POST to https://www.hamqth.com/api/v2/login:

POST /api/v2/login
Content-Type: application/json

{"callsign": "OK2CQR", "password": "secret"}

The answer is a token, valid for 60 minutes (expiresIn is in seconds):

{"token": "4f9c…e21a", "expiresIn": 3600}

Send it with every request to an endpoint marked login:

GET /api/v2/callbook/DL1ABC
Authorization: Bearer 4f9c…e21a

Without a token, or with an expired one, the answer is 401: log in again and repeat the request. Keep the token for the hour rather than logging in before every request. A wrong password is 401; after several wrong passwords the login is refused for a while with 429 and a Retry-After header (seconds), even with the right password.

Callbook lookup (login)

GET https://www.hamqth.com/api/v2/callbook/{callsign}, e.g. /api/v2/callbook/OK2CQR. A portable callsign finds the home record when it has none of its own (OK2CQR/P gives OK2CQR); its / may be sent as is or encoded (OK2CQR%2FP).

includebio adds the station's biography as plain text
appname of your program, for the lookup statistics (optional, at most 64 characters)
formatjson (default) or xml
{
  "callsign": "OK2CQR",
  "nick": "Petr",
  "name": "Petr Hlozek",
  "qth": "Neratovice",
  "dxcc": 503,
  "country": "Czech Republic",
  "continent": "EU",
  "cq": 15,
  "itu": 28,
  "utcOffset": 1.0,
  "location": {"lat": 50.253446, "lon": 14.515041, "grid": "JO70GG"},
  "address": {
    "name": "Petr Hlozek",
    "street": ["17. listopadu 1065"],
    "city": "Neratovice",
    "zip": "27711",
    "country": "Czech Republic",
    "dxcc": 503
  },
  "region": {"district": "BME", "usState": null, "usCounty": null, "oblast": null, "dok": null},
  "iota": null,
  "qsl": {"via": null, "bureau": true, "direct": true, "lotw": true, "eqsl": true},
  "email": "petr@example.com",
  "birthYear": 1982,
  "licensedSince": 1998,
  "links": {"web": "http://www.ok2cqr.com", "facebook": null, "twitter": null, "youtube": null, "linkedin": null},
  "picture": "https://www.hamqth.com/userfiles/o/ok/ok2cqr/_header/header.jpg?ver=13",
  "profile": "https://www.hamqth.com/ok2cqr"
}
utcOffsethours from UTC, +1 for Central Europe
address.dxccDXCC entity of the postal address, may differ from the station's
qsltrue / false as the station says, null when it does not say
picturethe station's own picture, null when there is none
name, address, email, birthYear, licensedSince, links (except web), bionull when the station hides them on its privacy page

In XML the root element is <callbook> and every street line is a <line> in <street>. An unknown callsign is 404.

Recent activity (login)

GET https://www.hamqth.com/api/v2/callbook/{callsign}/activity: DX cluster spots of and by the callsign and RBN spots of it (50 newest), QSOs with it in the logs uploaded to HamQTH (20 newest), and the newest QSOs of its own log (20), newest first. format=xml works as everywhere.

{
  "callsign": "OK2CQR",
  "spots": [
    {"source": "rbn", "spotter": "EA1DAV", "dxcall": "OK2CQR", "freq": 10109.5, "comment": "CW 4 dB 26 WPM CQ", "time": "2026-10-01T18:00:09Z"},
    {"source": "cluster", "spotter": "OK1ABC", "dxcall": "OK2CQR", "freq": 14025.0, "comment": "tnx QSO", "time": "2026-10-01T17:12:00Z"}
  ],
  "inLogs": [
    {"log": "DL1ABC", "date": "2026-09-30", "band": "20M", "mode": "CW"}
  ],
  "log": [
    {"call": "W1AW", "date": "2026-10-01", "band": "30M", "mode": "CW"}
  ]
}

source is cluster or rbn; inLogs[].log is the station whose log has the QSO. In XML the items are <spot> and <qso>.

DXCC

DXCC entity, zones and coordinates of a callsign from OK1RR's DXCC tables. No login. Example: https://www.hamqth.com/api/v2/dxcc?callsign=U3AP

callsignthe callsign
dateQSO date, YYYY-MM-DD (optional, default today): old prefixes and deleted entities resolve as they were on that day
entityinstead of a callsign: an entity by its DXCC (ADIF) number, 1–999
formatjson (default) or xml
{
  "callsign": "U3AP",
  "date": "2026-10-03",
  "details": "Russia (European), Gorod Moskva (MA), World War II. Veteran",
  "continent": "EU",
  "waz": 16,
  "itu": 29,
  "lat": 55.75,
  "lon": 37.62,
  "utcOffset": 4.0,
  "entity": {"adif": 54, "name": "Russia (European)", "continent": "EU", "waz": 16, "itu": 29, "lat": 56.0, "lon": 38.0, "utcOffset": 3.0, "deleted": false}
}

The callsign's own values (details, zones, coordinates) can be more precise than its entity's. entity=54 answers the entity object alone. utcOffset is hours from UTC (+3 for Moscow; v1 had the opposite sign). A callsign without a DXCC entity is 404.

DX cluster spots

Spots of the DX cluster, newest first, with the filters of its DX cluster tab. No login. Example: https://www.hamqth.com/api/v2/spots?bands=20M,40M&modes=CW&cont=NA&limit=20

bands<160M, 160M, 80M, 60M, 40M, 30M, 20M, 17M, 15M, 12M, 10M, 6M, 4M, 2M, 1.25M, 70CM, 33CM+; all when left out
modesCW, SSB, DIGI; all when left out. FT8, RTTY… count as DIGI however the spotter filed them; a spot of unknown mode passes any mode filter.
contcontinent of the spotted station: AF, AN, AS, EU, NA, SA, OC; all when left out
fromContcontinent of the spotter, same values
waz, ituzones of the spotted station, e.g. 14,15; * or left out = all
callsonly these callsigns, at most 30; a callsign also matches its portable forms
lotw, eqsl1: only stations using LoTW / eQSL
limitnumber of spots, 1–200 (default 60)
includelocations: add the position of the spotted stations and spotters, see station locations
formatjson (default) or xml
{
  "spots": [
    {
      "spotter": "W3LPL",
      "dxcall": "A71EM",
      "freq": 28003.6,
      "band": "10M",
      "mode": "CW",
      "comment": "Heard in MD",
      "time": "2026-10-03T07:58:00Z",
      "dxcc": 376,
      "country": "Qatar",
      "continent": "AS",
      "lotw": true,
      "eqsl": true
    }
  ]
}

freq is in kHz, mode CW, SSB, DIGI or null when unknown. Spots come in every few seconds; please do not ask more often than every 15 seconds.

RBN spots

The data of the RBN tab of the DX cluster, with the same filters. Every heard signal is one row: a station heard on two bands, or a multi-multi station with two transmitters on one band, gives two rows. Reports of one callsign and mode within 1 kHz of each other are one signal (skimmers read the same signal a few hundred Hz apart).

Request

https://www.hamqth.com/api/v2/rbn?bands=20M,40M&modes=CW&fromCont=EU&maxAge=300&sort=freq

bands160M, 80M, 60M, 40M, 30M, 20M, 17M, 15M, 12M, 10M, 6M, 2M; all when left out
modesCW, RTTY, PSK31, PSK63; all when left out
contcontinent of the spotted station: AF, AN, AS, EU, NA, SA, OC; all when left out
fromContcontinent of the skimmer (receiver), same values; all when left out
wazWAZ (CQ) zones of the spotted station, e.g. 14,15; * or left out = all
ituITU zones of the spotted station, e.g. 27,28; * or left out = all
callsonly these callsigns, at most 30, e.g. OK2CQR,OL7M. A callsign also matches its portable forms (OK2CQR/P, DL/OK2CQR).
maxAgeonly reports from the last N seconds, 1–3600 (default 1200)
sortage (newest first, default), freq or call
includelocations: add the position of the spotted stations and skimmers, see station locations
formatjson (default) or xml

JSON answer

{
  "spots": [
    {
      "dxcall": "OL7M",
      "band": "20M",
      "mode": "CW",
      "freq": 14025.3,
      "age": 12,
      "skimmers": [
        {"call": "DK9IP", "snr": 24},
        {"call": "OH6BG", "snr": 17}
      ]
    },
    {
      "dxcall": "OL7M",
      "band": "40M",
      "mode": "CW",
      "freq": 7012.1,
      "age": 40,
      "skimmers": [
        {"call": "SE5E", "snr": 9}
      ]
    }
  ]
}
freqkHz, from the newest report of the signal
ageseconds since the newest report of the signal
skimmersskimmers that heard the signal, the best SNR (dB) of each, strongest first

Nothing found is an empty list: {"spots": []}.

XML answer

<?xml version="1.0" encoding="UTF-8"?>
<spots>
  <spot>
    <dxcall>OL7M</dxcall>
    <band>20M</band>
    <mode>CW</mode>
    <freq>14025.3</freq>
    <age>12</age>
    <skimmers>
      <skimmer call="DK9IP" snr="24"/>
      <skimmer call="OH6BG" snr="17"/>
    </skimmers>
  </spot>
</spots>

Station locations

To draw spots on a map, add include=locations to DX cluster spots or RBN spots. The answer then also has a locations list: every station of the answer (spotted, spotter, skimmer) whose position is known, once, sorted by callsign. A station that is not in it has no known position. Without include the answer stays as it was.

{
  "spots": [ … ],
  "locations": [
    {"call": "DK9IP", "grid": "JO31", "lat": 51.5, "lon": 7.0, "source": "skimmer"},
    {"call": "OL7M", "grid": "JO70", "lat": 50.5, "lon": 15.0, "source": "callbook"},
    {"call": "OL7M/P", "grid": "JO70", "lat": 50.07, "lon": 14.42, "source": "dxcc"}
  ]
}
grid4-character Maidenhead locator (1° × 2°); never more exact, the API is public
lat, lonthe centre of the locator, for dxcc the position of the prefix
source skimmer: where the RBN skimmer stands, from the RBN node list (refreshed daily); callbook: the HamQTH callbook; dxcc: only the country or call area of the prefix, for callsigns not in the callbook and for portable ones (OK1ABC/P, DL/OK1ABC are not at home)

In XML the list is <locations> inside <spots>; RBN spots have <location call="DK9IP" grid="JO31" lat="51.5" lon="7.0" source="skimmer"/>, DX cluster spots the same values as elements.

QSO verification

The simple award verification protocol: is a QSO with mycall in the log hiscall uploaded to HamQTH? No login. Example: https://www.hamqth.com/api/v2/verify?mycall=J49C&hiscall=OK2CQR&date=2013-06-20&band=12M

mycallthe callsign asking (the one in hiscall's log)
hiscallthe station whose log is checked
dateQSO date, YYYY-MM-DD
bande.g. 20M
timeoptional, QSO start HH:MM UTC; must match exactly
modeoptional, e.g. CW
{"log": true, "found": true}

log: hiscall has a log on HamQTH; found: the QSO is in it. Both are false when there is no log.

Log upload (login)

Uploads a whole log: it replaces the log on HamQTH, there are no partial uploads (use real-time QSO for single QSOs). A multipart/form-data POST to https://www.hamqth.com/api/v2/log/uploads with:

filethe log: ADIF (.adi, .adif), or ADIF compressed in zip, gz, tar.gz, tar.bz2, rar or 7z; at most 20 MB
callsignoptional: the log of another callsign you manage on HamQTH; your own when left out
curl -H "Authorization: Bearer $TOKEN" -F file=@mylog.adi https://www.hamqth.com/api/v2/log/uploads

The import runs in the background. The answer is 202 with the upload's id and the URL to ask for its result (also in the Location header):

{
  "id": 2195,
  "callsign": "OK2CQR",
  "file": "mylog.adi",
  "format": "adi",
  "size": 183520,
  "status": "queued",
  "createdAt": "2026-10-03T08:15:02Z",
  "finishedAt": null,
  "statusUrl": "https://www.hamqth.com/api/v2/log/uploads/2195"
}

GET the statusUrl (login) until status is done or failed (from queued and processing); a log of a few thousand QSOs takes seconds. The answer adds:

{
  …,
  "status": "done",
  "qsoCount": 41250,
  "error": null,
  "warnings": [
    {"type": "zone", "count": 3, "example": "CQZ=99", "message": "Invalid CQ/ITU zone, replaced by the zone of the DXCC entity."}
  ],
  "rejected": {
    "total": 1,
    "records": [
      {"reason": "bad_call", "message": "Invalid callsign X!.", "record": "CALL=X! QSO_DATE=20240105 TIME_ON=1200 BAND=20M MODE=CW"}
    ]
  }
}

error says why a failed import failed; the log on HamQTH is left as it was. rejected.records lists the first 1000 QSOs that were skipped. The user gets the same result by e-mail. A file that cannot be imported at all (unknown format, too big) is 422 right away; a callsign you do not manage is 403.

Real-time QSO (login)

Adds, changes or deletes one QSO in the log as soon as it is saved in your program: https://www.hamqth.com/api/v2/log/qso, a JSON body for POST and PUT. The QSO is given by its ADIF fields, lower-case ADIF names and ADIF values, and is checked like a QSO of an uploaded log. callsign chooses the log of another callsign you manage; your own when left out.

New QSO: POST

POST /api/v2/log/qso
Authorization: Bearer 4f9c…e21a
Content-Type: application/json

{
  "qso": {
    "call": "DL1ABC",
    "qso_date": "20240105",
    "time_on": "1200",
    "band": "20M",
    "mode": "CW",
    "freq": "14.025",
    "rst_sent": "599",
    "rst_rcvd": "579",
    "dxcc": "230"
  }
}

call, qso_date, time_on and band or freq are required. Also stored: time_off, rst_sent, rst_rcvd, name, qth, qsl_sent, qsl_rcvd, qsl_via, qslsdate, qslrdate, iota, tx_pwr, gridsquare, my_gridsquare, cqz, ituz, cont, dxcc, state, cnty, submode and the lotw_ / eqsl_ QSL fields. Send dxcc when your program knows it; otherwise it is resolved from the callsign on the QSO date. The answer is 201 with the QSO as stored:

{"call": "DL1ABC", "date": "2024-01-05", "time": "12:00", "band": "20M", "mode": "CW", "freq": 14.025, "dxcc": 230}

Changed QSO: PUT

original identifies the QSO as it is in the log (call, qso_date, time_on, band, mode), qso is the whole new QSO; it replaces the old one:

{
  "original": {"call": "DL1ABC", "qso_date": "20240105", "time_on": "1200", "band": "20M", "mode": "CW"},
  "qso": {"call": "DL1ABC", "qso_date": "20240105", "time_on": "1200", "band": "40M", "mode": "CW", "rst_sent": "599"}
}

Deleted QSO: DELETE

The QSO by its fields in the query string (a DELETE has no body), callsign there too when needed:

DELETE /api/v2/log/qso?call=DL1ABC&qso_date=20240105&time_on=1200&band=40M&mode=CW
Authorization: Bearer 4f9c…e21a

The answer is 204 without a body. A QSO that is already in the log is 409 (POST, or a PUT onto another logged QSO), a QSO that is not there is 404, an invalid field 422, a callsign you do not manage 403. USB and LSB are stored as SSB, so send SSB to find such a QSO.

Solar data

Solar and geomagnetic indices as the DX cluster page shows them, read from DK0WCY every 5 minutes. No login. Example: https://www.hamqth.com/api/v2/solar

{
  "solarFlux": 112.2,
  "aIndex": 4,
  "kIndex": 3,
  "sunspotNumber": null,
  "solarActivity": "eruptive",
  "kielAIndex": 16,
  "currentKIndex": 3.4,
  "geomagneticField": "active",
  "aurora": "no",
  "indicesDate": "2026-10-04",
  "fetchedAt": "2026-10-05T08:25:00Z",
  "source": "http://dk0wcy.de/magnetogram/"
}
solarFluxsolar flux index (SFI) of indicesDate
aIndexBoulder A index of indicesDate
kIndexKiel K index of the last 3-hour period
sunspotNumbersunspot number (SSN) of indicesDate
solarActivityforecast, as DK0WCY words it: quiet, eruptive, …
kielAIndexKiel A index of indicesDate
currentKIndexKiel K index measured right now, with decimals
geomagneticFieldforecast, as DK0WCY words it: quiet, active, minor storm, …
auroraas DK0WCY words it: no, …
indicesDateday the daily indices are for, usually yesterday
fetchedAtwhen HamQTH last read the values; when DK0WCY is down, the last values stay and this time gets older

A value DK0WCY does not give at the moment is null. format=xml works as everywhere (root <solar>). The values change at most every 5 minutes, so please do not ask more often.

Errors

Every error is an HTTP status code with a problem details JSON body (Content-Type: application/problem+json, also for format=xml); detail says what is wrong:

{
  "type": "https://tools.ietf.org/html/rfc2616#section-10",
  "title": "Not Found",
  "status": 404,
  "detail": "Callsign ZZ9ZZZ not found."
}
401no token, an expired one, or a wrong password at login
403logged in, but not allowed (a log of a callsign you do not manage)
404nothing found (callsign, DXCC entity, QSO, upload)
409the QSO is in the log already
422an invalid parameter or field
429too many wrong passwords, wait Retry-After seconds
503a service behind the API is down for a moment (or has no data yet), try again later

An invalid parameter (an unknown band, maxAge=0, …) also gets violations, naming every wrong parameter:

{
  "type": "https://symfony.com/errors/validation",
  "title": "Validation Failed",
  "status": 422,
  "detail": "bands: Unknown value \"21M\", use one of 160M,80M,60M,40M,30M,20M,17M,15M,12M,10M,6M,2M.",
  "violations": [
    {
      "propertyPath": "bands",
      "title": "Unknown value \"21M\", use one of 160M,80M,60M,40M,30M,20M,17M,15M,12M,10M,6M,2M.",
      …
    }
  ]
}

Changelog

7 Oct 2026 – station locations for maps: include=locations on DX cluster and RBN spots.

5 Oct 2026 – solar data (GET /api/v2/solar).

3 Oct 2026 – every v1 endpoint has a v2 version: login, callbook lookup, recent activity, DXCC, DX cluster spots, QSO verification, log upload, real-time QSO; RBN spots before that. The OpenAPI document and the interactive reference describe all of them.

This is the original HamQTH API. It is legacy: still supported for backward compatibility, but new features go to API v2. When an endpoint has a v2 version, please use that in new code.


HamQTH provides a simple interface for application developers.
You can use:

HamQTH has very powerful log search function with nice graphical statistics - look at my own profile
List of apps supporting HamQTH is on dedicated site.

The HamQTH API is available also on http but it's only for backward compatibility. Using secure version is highly recommended!

DO NOT mix LF and CRLF line endings in the request to HamQTH API. RFC2616 requires that HTTP/1.1 only use CRLF. If you don't, the server may answer HTTP/1.1 400 to all malformed headers.

API v2 has a newer version: Callbook lookup in API v2. This endpoint keeps working for existing applications.

If you want to use HamQTH callbook query search in your logging program, you don't need to parse HTML code to get the data. You can use our XML service. However, the user who wants to use data from HamQTH, has to be registered here.

How XML search works?

At first, you have to ask for session ID:
https://www.hamqth.com/xml.php?u=username&p=password
where
uusername registered on HamQTH (station callsign)
puser's password
If your username or password is correct, you'll get something like this:
    <?xml version="1.0"?>
    <HamQTH version="2.8" xmlns="https://www.hamqth.com">
    <session>
    <session_id>09b0ae90050be03c452ad235a1f2915ad684393c</session_id>
    </session>
    </HamQTH>
  
If your username or password is NOT correct, XML search returns:
    <?xml version="1.0"?>
    <HamQTH version="2.8" xmlns="https://www.hamqth.com">
    <session>
    <error>Wrong user name or password</error>
    </session> 
    </HamQTH>
  
Session ID is valid for one hour. After it expires, you need to request for new one.
If your session expired or the query is not valid, XML query will return:
    <?xml version="1.0"?>
    <HamQTH version="2.8" xmlns="https://www.hamqth.com">
    <session>
    <error>Session does not exist or expired</error>
    </session> 
    </HamQTH>
  

How do I search for callsign data?

Now we have our session ID and can try to search for callsign e.g. OK2CQR:
https://www.hamqth.com/xml.php?id=09b0ae90050be03c452ad235a1f2915ad684393c&callsign=ok2cqr&prg=YOUR_PROGRAM_NAME
where
idsession ID requested before
callsigncallsign you are looking for
YOUR_PROGRAM_NAMEName of the application using XML search (without spaces)
If your session is valid and callsign exists you get this XML structure:
    <?xml version="1.0"?>
    <HamQTH version="2.8" xmlns="https://www.hamqth.com">
    <search> 
	<callsign>ok2cqr</callsign>
	<nick>Petr</nick> 
	<qth>Neratovice</qth> 
	<country>Czech Republic</country>
     	<adif>503</adif>
	<itu>28</itu> 
	<cq>15</cq> 
	<grid>jo70gg</grid> 
	<adr_name>Petr Hlozek</adr_name> 
	<adr_street1>17. listopadu 1065</adr_street1> 
	<adr_city>Neratovice</adr_city> 
	<adr_zip>27711</adr_zip> 
	<adr_country>Czech Republic</adr_country> 
     	<adr_adif>503</adr_adif>
	<district>GZL</district>
	<lotw>Y</lotw> 
	<qsl>Y</qsl> 
	<qsldirect>Y</qsldirect> 
	<eqsl>Y</eqsl> 
	<email>petr@ok2cqr.com</email>
	<jabber>petr@ok2cqr.com</jabber>
	<skype>PetrHH</skype> 
	<birth_year>1982</birth_year> 
	<lic_year>1998</lic_year> 
	<web>https://www.ok2cqr.com</web>
	<latitude>50.07</latitude>
	<longitude>14.42</longitude>
	<continent>EU</continent>
        <utc_offset>-1</utc_offset>
	<picture>https://www.hamqth.com/userfiles/o/ok/ok2cqr/_profile/ok2cqr_nove.jpg</picture>
    </search> 
    </HamQTH>
Address, e-mail, birth and licence year, social networks and biography the station hides on its privacy page are left out (the always-present address elements stay, empty); the same goes for adif.php and xml_bio.php.
where
callsigncallsign you searched
nickname used on the air
qthcallsign's QTH
countrycountry related to callsign, not to the address
adifADIF ID of country related to callsign
ituITU zone
CQCQ (WAZ) zone
gridstation locator
adr_nameaddress name
adr_street1street address
adr_street2street address
adr_street3street address
adr_citycity address
adr_zipzipcode
adr_countrycountry related to the address
adr_adifADIF ID of address country
districtstation district
us_stateUS state (USA stations only)
us_countyUS county (USA stations only)
oblastsomething like district (Russian stations)
dokDOK (DL stations)
iotaIOTA reference number
qsl_viaQSL information
lotwY - uses LoTW, N - doesn't use LoTW, ? - we don't know
eqslY - uses eQSL, N - doesn't use eQSL, ? - we don't know
qslY - accept QSL via bureau, N - doesn't accept QSL via bureau, ? - we don't know
qsldirectY - accept direct QSL card, N - doesn't accept direct QSL, ? - we don't know
emailemail
jabberjabber
icqicq number
msnMSN
skypeSkype
birth_yearYear of birth
lic_yearLicenced since
picturelink to user's picture
latitudestation position - latitude
longitudestation position - longitude
continentcontinent
utc_offsetoffset to UTC time in station location
facebooklink to Facebook profile
twitterlink to user's Twitter feed
gpluslink to GooglePlus profile
youtubelink to user's YouTube channel
linkedinlink to user's LinkedIn profile
flickerlink to user's flicker profile
vimeolink to user's Vimeo channel
If callsign doesn't exist in HamQTH database, you get this:
    <?xml version="1.0"?>
    <HamQTH version="2.8" xmlns="https://www.hamqth.com">
    <session>
      <error>Callsign not found</error>
    </session>
    </HamQTH>
  

How do I get callsign bio?

If you have session ID, it's very easy. Just use this http request:
https://www.hamqth.com/xml_bio.php?id=09b0ae90050be03c452ad235a1f2915ad684393c&callsign=ok2cqr&strip_html=1
where:
idsession ID requested before
callsigncallsign's bio you are looking for
strip_html1 - if you want to get plain text without HTML tags (default value), 0 - you want to get as is, also with HTML code
The result when station is at HamQTH:
<?xml version="1.0"?>
<HamQTH version="2.8" xmlns="https://www.hamqth.com">
<search> 
  <callsign>ok2cqr</callsign>
  <bio>my looong biography</bio> 
</search> 
</HamQTH>
    
where:
callsigncallsign you searched
biothe bio information text
If callsign doesn't exist in HamQTH database, you get this:
<?xml version="1.0"?>
<HamQTH version="2.8" xmlns="https://www.hamqth.com">
  <session>
  <error>Callsign not found</error>
</session>
</HamQTH>
    
If you need only longitude and latitude and other data is not interesting for you, you can use xml_latlong.php and you'll get only coordinates. The output is the same like from XML search.

XML recent activity search

API v2 has a newer version: Recent activity in API v2. This endpoint keeps working for existing applications.

Recent activity of any callsign is collected from Reverse beacon network and dx cluster. It's very usefull utility especially for dx expedition and rare stations. This inteface also makes accessible list of QSO with searched station in the HamQTH logbook database and list of most recent QSO from station's log (if any exists).

How it works?

This search also needs xml session id. How to get it is described at XML callbook search. If you have it, you can try query like this:

https://www.hamqth.com/xml_recactivity.php?id=session_id&callsign=ok2cqr&rec_activity=1&log_activity=1&logbook=1
where:
idsession ID requested before
callsigncallsign you are looking for
rec_activity1 - include also data from RBN and dx clusters (default value), 0 do not add RBN and DX clusters data
log_activity1 - include 20 qso QSO from HamQTH logbook (default value), 0 do not add logbook data
logbook1 - include last 20 QSO from HamQTH station's logbook (default value), 0 do not add logbook data
If callsign doesn't exist in HamQTH database, you get this:
    <?xml version="1.0"?>
    <HamQTH version="2.8" xmlns="https://www.hamqth.com">
      <session>
      <error>Callsign not found</error>
    </session>
    </HamQTH>
        
and if it does, you'll get this XML:
    <?xml version="1.0"?>
    <HamQTH version="2.8" xmlns="https://www.hamqth.com">
    <search>
      <activity>
        <data>
          <source>DXC</source>
          <spotter>ZL2HAM</spotter>  
          <callsign>OK2CQR</callsign>
          <note>calling CQ</note>
          <freq>21025.0</freq>
          <date>2011-09-10</date>
          <time>05:34:28</time>
        </data>    
        <data>
          <source>RBN</source>
          <spotter>IK3STG</spotter>
          <callsign>OK2CQR</callsign>
          <note>13 dB  34 WPM  CQ</note>
          <freq>14026.3</freq>
          <date>2011-09-07</date>
          <time>13:34:28</time>
        </data>    
      </activity>
      <log_activity>
        <data>
          <callsign>PT0S</callsign>
          <band>20M</band>
          <mode>CW</mode>
          <date>2012-11-13</date>
        </data>
        <data>
          <callsign>OK1RR</callsign>
          <band>40M</band>
          <mode>CW</mode>
          <date>2012-09-07</date>
        </data>
      </log_activity>
      <logbook>
        <data>
          <callsign>AA3B</callsign>
          <band>15M</band>
          <mode>CW</mode>
          <date>2012-11-11</date>
        </data>
        <data>
          <callsign>OK7WA</callsign>
          <band>80M</band>
          <mode>SSB</mode>
          <date>2012-05-07</date>
        </data>
      </logbook>
    </search>
    </HamQTH>
        
where:
activitysection with records from RBN and DX clusters network
  sourcesource of the data - RBN or DXC
  spotterstation that send the spot (DXC) or callsign of reverse beacon network station
  callsignspotted callsign
  noteshort note related to the spot
  freqfrequency in kHz
  datespot sent date
  timespot sent time
log_activitysection with records HamQTH logbook - list of station that has callsign in their logs
  callsignstation that has QSO in the log with station you are looking for
  modemode of operating
  bandband like in ADIF spec e.g. 160M, 40M etc.
  dateQSO date
logbooksection with records in station's HamQTH logbook - list of 20 most recent QSOs in station's log
  callsignwkd callsign
  modemode of operating
  bandband like in ADIF spec e.g. 160M, 40M etc.
  dateQSO date

API v2 has a newer version: DXCC in API v2. This endpoint keeps working for existing applications.

HamQTH also provides DXCC search based on Martin's (OK1RR) DXCC tables used in CQRLOG. The tables are excellent and probably the best ever. It provides excellent detail info e.g. callsign U3AP - https://www.hamqth.com/dxcc.php?callsign=U3AP you don't get only basic info that it is European Russia, but also Gorod Moskva (MA), World War II. Veteran.

How DXCC XML search works?

It is very easy. If you query HamQTH like this: https://www.hamqth.com/dxcc.php?callsign=U3AP where:

callsignthe callsign you are looking for DXCC info
You'll get this XML structure:
      <?xml version="1.0"?>
      <HamQTH version="2.8" xmlns="https://www.hamqth.com">
      <dxcc>
        <callsign>U3AP</callsign>
        <name>Russia (European)</name>
        <details>Russia (European), Gorod Moskva (MA), World War II. Veteran</details>
        <continent>EU</continent>
        <utc>-3</utc>
        <waz>16</waz>
        <itu>29</itu>
        <lat>55.75</lat>
        <lng>37.63</lng>
        <adif>54</adif>
      </dxcc>
      </HamQTH>      
    
There is another way. If you set callsign parameter to adif number (https://www.hamqth.com/dxcc.php?callsign=503), you'll get something like this:
      <?xml version="1.0"?>
      <HamQTH version="2.8" xmlns="https://www.hamqth.com">
      <dxcc>
        <name>Czech Republic</name>
        <continent>EU</continent>
        <utc>-1</utc>
        <waz>15</waz>
        <itu>28</itu>
        <lat>50.07</lat>
        <lng>14.42</lng>
        <adif>503</adif>
      </dxcc>
      </HamQTH>      
    
You can use it for free, without any registration. Have a fun!

LOG upload

API v2 has a newer version: Log upload in API v2. This endpoint keeps working for existing applications.

HamQTH also has very nice and powerful log search function. To make upload much easier, I've created simple page for uploading logs from mobile phone or your own application https://www.hamqth.com/prg_log_upload.php. Remember you always have to upload whole log. HamQTH doesn't support partial upload.

How log upload works?

It's very similar to log upload function in station profile but much easier to add to your application. To upload the log, you have to use POST method with these parameters:
u - username
p - password
c - callsign (if empty, username as callsign will be used)
f - file name of the uploading log
send_log - send OK as value (like user click on the OK button)
The file size is limited to 20MB but you can compress ADIF with zip, rar, 7zip, tar.gz or tar.bz2. File name in the archive has to have adi or adif extension otherwise won't be imported. If you'll upload plain ADIF file, adi/adif and txt extensions are allowed.
Like the upload from user's profile, log is not imported in run-time but on background. User will be informed via email about import progress. After you send POST request, there are four error messages you can get:
User parameter missing
Password parameter missing
Wrong username or password
You cannot upload log for this callsign
And after successful upload you'll get this:
Log uploaded successfully
I hope, they are self-explained. If there will be any problem with ADIF file itself, user will be informed via email.

Examples

I'm pure Linux user and use CQRLOG for my daily logging. It has auto backup function which always after I close the program exports all QSO into ADIF file and stores into defined directory (/home/ok2cqr/Ubuntu One/cqrlog_zaloha on my computer). If I want to upload last log backup to HamQTH, I use this script:
#!/bin/bash
BACKUPDIR="/home/ok2cqr/Ubuntu One/cqrlog_zaloha/"
USERNAME=ok2cqr
PASSWORD=my_password
cd "$BACKUPDIR"
curl -F f=@`ls | tail -n 1` -F send_log=OK -F u=$USERNAME -F p=$PASSWORD https://hamqth.com/prg_log_upload.php
That's all! I have an icon on the panel and when I click on it, it makes backup of my log to HamQTH. Very easy and powerfull. You can also create program to use Windows command line. I'm not so keen in windows scripting but if you are, please send me your script and I'll put it here.

Real-time QSO upload

API v2 has a newer version: Real-time QSO in API v2. This endpoint keeps working for existing applications.

You can upload individual QSO to HamQTH logbook in real-time as well. Use POST request to https://www.hamqth.com/qso_realtime.php with these parameters:
u - username
p - password
c - callsign (if empty, username as callsign will be used)
adif - the QSO in ADIF format
prg - name of your application (without version number)
cmd - command to real time upload function (insert, update, delete)

The result will be send as HTTP status code with message in the body. The HTTP status codes are:

  • 403 Forbidden: Access denied. Your username and/or password was incorrect. The QSO will NOT be logged.
  • 500 Internal error: This may occurs if the server has any problem in general or there is a problem with your ADIF file. In the body should be more information what happened. The QSO will NOT be logged.
  • 400 QSO Rejected: QSO was rejected for some reason e.g. wrong band, already exists in database etc. The QSO will NOT be logged.
  • 200 QSO OK: QSO was successfully saved into database.

HamQTH supports these ADIF fields:
QSO_DATE, TIME_ON, TIME_OFF, CALL, FREQ, MODE, RST_S, RST_R, NAME, QTH, QSL_SENT, QSLSDATE, QSL_RCVD, QSLRDATE, QSL_VIA, IOTA, TX_PWR, ITUZ, CQZ, CONT, GRIDSQUARE, MY_GRIDSQUARE, STATE, CNTY, COMMENT, DXCC, BAND, LOTW_QSL_SENT, LOTW_QSLSDATE, LOTW_QSL_RCVD, LOTW_QSLRDATE, EQSL_QSL_SENT, EQSL_QSLSDATE, EQSL_QSL_RCVD, EQSL_QSLRDATE

All values should not be HTML escaped.

Please DO NOT use this real time access to batch upload of thousands of QSOs. If your you are uploading log for the first time, upload whole ADIF file through the website.

New QSO

HamQTH will accept new QSO record in ADIF format with at least QSO_DATE, TIME_ON, CALL, MODE, BAND, RST_S, RST_R fields. If you try to post less fields, you'll get HTTP status code 400 with error message in the body.

Update existing QSO

To specify the QSO you want to update in the database, you have to post old values of qso date, time on, callsign and mode. Without these values server won't be able to find your QSO and update it. Old values are also part of ADIF ouput but with OLD_ prefix - OLD_QSO_DATE, OLD_TIME_ON, OLD_CALL, OLD_BAND, OLD_MODE. E.g. you want to update name in the QSO, send only all mandatory fields (OLD_QSO_DATE etc.) and NAME field.

Delete QSO

Specify QSO to delete using OLD_QSO_DATE, OLD_TIME_ON, OLD_CALL, OLD_BAND and OLD_MODE field in ADIF output.

Please DO NOT use this real time QSO upload to batch delete of whole log. If you want to delete it, just disable log search function in your profile preferences.
To be sure that your DXCC statistics will be correct, sending DXCC resp. OLD_DXCC field with every QSO is strongly recommended!

DX cluster spots

API v2 has a newer version: DX cluster spots in API v2. This endpoint keeps working for existing applications.

HamQTH provides DX cluster spots feed in simple CSV format with this structure:

        Call^Frequency^Date/Time^Spotter^Comment^LoTW user^eQSL user^Continent^Band^Country name
    
No registration needed, just use this link:
https://www.hamqth.com/dxc_csv.php?limit=10 where:
limitmaximim of downloaded spots, default is 60, max is 200
bandreturn spots only for specified band e.g. dxcc_csv.php?limit=10&band=80M retuns last 10 spots from 80M band
You'll get this:
CT1ISH^21255.0^PI4ZU^DX & Contest Club Station^1311 2015-02-28^^^EU^15M^Netherlands^263
IZ8GNR^28478.0^H91T^NA-072^1310 2015-02-28^^^NA^10M^Panama^88
R8WZ^28491.2^DR50RRDXA^tnx QSO^1309 2015-02-28^^^EU^10M^Germany^230
IK2AHU^14315.0^IW2NXI/P^dai-lb1214^1309 2015-02-28^^^EU^20M^Italy^248
IZ4AFM^14315.0^IW2NXI/P^DAI LB1214^1309 2015-02-28^^^EU^20M^Italy^248
DL5JK^28495.0^OA6Q^Georg 5/9 wie jedes Jahr^1309 2015-02-28^L^E^SA^10M^Peru^136
HA8IE^10110.0^HV0A^pse activity on 30m!^1309 2015-02-28^L^^EU^30M^Vatican^295
HA8WX^28405.0^TO6D^simplex^1309 2015-02-28^L^^NA^10M^Guadeloupe Island^79
W3LPL^28003.6^A71EM^Heard in MD^1309 2015-02-28^L^E^AS^10M^Qatar^376
  
The latest number is ADIF country ID.

Please do not refresh the page often then every 10 seconds. Spots from DX spider are saved every 15 seconds so shorter time period won't return any new spots.

Simple award verification protocol

API v2 has a newer version: QSO verification in API v2. This endpoint keeps working for existing applications.

Numerous web services and web sites all over the world provide electronic storage of “station logs”. Whatever we call it, eQSL, LoTW, all of them are but centrally managed collections of ham radio station logs in databases. Small amateur radio societies, often issue awards for contacts with their members. “Worked all members” is the simplest possible award imaginable. A really small ham radio society could theoretically avoid checking QSL cards, by inspecting their members’ log books .... continue in SAVP-SimpleAwardVerificationProtocol-short.pdf and SAVPGuidelines.pdf written by Jindra, OK4RM.

Example

HTTP client will send verification request using GET method:
https://www.hamqth.com/verifyqso.php?mycall=j49c&hiscall=ok2cqr&date=20130620&band=12M
The result is described in specification above.

JSON DXCC search

API v2 has a newer version: DXCC in API v2. This endpoint keeps working for existing applications.

The same like XML DXCC search but it returns data in JSON.

Example

https://www.hamqth.com/dxcc_json.php?callsign=U3AP

and you'll get this:
{"callsign":"U3AP", "name":"Russia (European)", "details":"Russia (European), Gorod Moskva (MA), World War II. Veteran", "continent":"EU",
"utc":"-3", "waz":"16", "itu":"29", "lat":"55.75", "lng":"37.63", "adif":"54"}

Agregated data from RBN in JSON and XML

Superseded by RBN spots in API v2: this endpoint keeps one entry per callsign, so a station heard on more bands (or a multi-multi station) is mixed into one entry. It stays here for existing applications.

In the DX cluster, there is a RBN tab where you can see data from Reverse Beacon Network. You can provide the same function in your software using this api.

Example

https://www.hamqth.com/rbn_data.php?data=1&band=160,80,60,40,30,20,17,15,12,10,6,2&fromcont=EU&mode=CW,RTTY,PSK31,PSK63&cont=AF,AN,AS,EU,NA,SA,OC&waz=*&itu=*&age=60&order=3
where:
data=1this parameter is required for some internal reasons
bandreturn spots only for specified band, it uses ADIF band specification but numbers only e.g. 80, 40, 30 etc.
fromcontreturn spots only from receivers located on the specific continet e.g. EU, you can specify more continets e.g. fromcont=EU,AS
modereturn spots only with specific mode. Right now you can use CW, RTTY, PSK31 and PSK63
contreturn spots only when the continent of spotted station match to AF,AN etc.
wazreturn spots only when the WAZ zone of spotted station is 10,12,13. When you want to get all zones, use *
wazreturn spots only when the ITU zone of spotted station is 27,2625. When you want to get all zones, use *
agereturn spots only from last XX seconds e.g. age=120 will return spotted station from last two minutes
orderreturn spots sorted by frequecy (order=1), callsign (order=2) or spot age (order=3)
xmlwith xml=1 returned data is in XML format

and you'll get this:

            {
            "DL2IAD":{"dxcall":"DL2IAD","freq":"7 023.4","mode":"CW","age":4,"lsn":{"OL7M":16}},"OK1TPI":{"dxcall":"OK1TPI","freq":"7 026.1","mode":"CW","age":4,"lsn":{"OL7M":16,"F6IIT":34}},
            "EA5EBD":{"dxcall":"EA5EBD","freq":"7 039.1","mode":"CW","age":4,"lsn":{"F6IIT":34,"S50ARX":21,"HA2KSD":19,"OL7M":16,"OE6TZE":10}},
            "EA1TG":{"dxcall":"EA1TG","freq":"7 031.0","mode":"CW","age":10,"lsn":{"F6IIT":34,"S50ARX":21,"OL7M":16,"HA2KSD":7,"DK0TE":5,"HB9DCO":5,"OE6TZE":5,"DK3UA":4}},
            "EP4HR":{"dxcall":"EP4HR","freq":"14 023.0","mode":"CW","age":10,"lsn":{"F6IIT":34,"S50ARX":21,"HA2KSD":19,"OL7M":16,"OE6TZE":10,"DK3UA":4,"UD4FD":9}},
            "UR5LQY":{"dxcall":"UR5LQY","freq":"14 048.1","mode":"CW","age":10,"lsn":{"F6IIT":34,"SM2IUF":26,"HA2KSD":19,"S50ARX":17,"OL7M":16,"OE6TZE":10,"UD4FD":9,"DK3UA":4}},
            "R5LQY":{"dxcall":"R5LQY","freq":"14 048.0","mode":"CW","age":10,"lsn":{"OH6BG":35,"F6IIT":34,"HA1VHF":29,"DL3KR":21,"DL8TG":20,"DL9GTB":19,"HA2KSD":19,"S50ARX":17,"OL7M":16,"HB9BXE":16,"DO4DXA":12,"HB9JCB":11,"F5RRS":10,"OE6TZE":10,"UD4FD":9,"DL1RNN":9,"DK3UA":4,"G0LUJ":3,"DK9IP":2}},
            "WB2UZE":{"dxcall":"WB2UZE","freq":"7 014.5","mode":"CW","age":16,"lsn":{"F6IIT":11,"S50ARX":17,"HA2KSD":19,"OL7M":16,"OE6TZE":10,"DK3UA":4,"UD4FD":9,"DL1RNN":9}},
            "IK2MMP":{"dxcall":"IK2MMP","freq":"7 028.8","mode":"CW","age":16,"lsn":{"HA2KSD":37,"DL3KR":22,"S50ARX":17,"OL7M":16,"F6IIT":11,"OE6TZE":10,"UD4FD":9,"DL1RNN":9,"DK3UA":4}},
            "ON6MH":{"dxcall":"ON6MH","freq":"10 111.0","mode":"CW","age":16,"lsn":{"HA2KSD":37,"S50ARX":17,"OL7M":16,"F6IIT":11,"OE6TZE":10,"UD4FD":9,"ON6ZQ":9,"DL1RNN":9,"IZ2CPS":7,"DK3UA":4,"CT1BOH":2}},
            "CS3B":{"dxcall":"CS3B","freq":"18 109.9","mode":"CW","age":16,"lsn":{"F6IIT":34,"HA2KSD":19,"S50ARX":17,"HB9BXE":16,"OL7M":16,"OE6TZE":10,"DL1RNN":9,"UD4FD":9,"DK3UA":4,"G0LUJ":3,"HB9DCO":18}},
            "F1UQ":{"dxcall":"F1UQ","freq":"14 031.9","mode":"CW","age":38,"lsn":{"F6IIT":34,"S50ARX":21,"OL7M":16,"HA2KSD":7,"OE6TZE":5,"DK3UA":4,"CT7AHV":15}},
            "4X6TU":{"dxcall":"4X6TU","freq":"18 110.1","mode":"CW","age":38,"lsn":{"OH6BG":35,"F6IIT":34,"HA2KSD":19,"DL9GTB":19,"S50ARX":17,"HB9BXE":16,"OL7M":16,"F5RRS":10,"OE6TZE":10,"DL1RNN":9,"UD4FD":9,"DK3UA":4,"G0LUJ":3,"DK9IP":2,"SK3W":15}},
            "OJ9X":{"dxcall":"OJ9X","freq":"10 107.1","mode":"CW","age":40,"lsn":{"OH6BG":35,"F6IIT":34,"HA2KSD":19,"DL9GTB":19,"S50ARX":17,"HB9BXE":16,"OL7M":16,"F5RRS":10,"OE6TZE":10,"DL1RNN":9,"UD4FD":9,"DK3UA":18,"G0LUJ":3,"DK9IP":2,"SK3W":15}},
            "YP5XMAS":{"dxcall":"YP5XMAS","freq":"14 021.1","mode":"CW","age":40,"lsn":{"OH6BG":35,"F6IIT":34,"HA2KSD":19,"DL9GTB":19,"S50ARX":17,"HB9BXE":16,"OL7M":16,"F5RRS":10,"OE6TZE":10,"DL1RNN":9,"UD4FD":9,"DK3UA":18,"G0LUJ":3,"DK9IP":2,"SK3W":15,"SM2IUF":8}},
            "R4LA":{"dxcall":"R4LA","freq":"7 019.0","mode":"CW","age":50,"lsn":{"OH6BG":35,"F6IIT":34,"HA1VHF":29,"DL3KR":10,"DL8TG":20,"DL9GTB":19,"HA2KSD":19,"S50ARX":17,"OL7M":16,"HB9BXE":16,"DO4DXA":12,"HB9JCB":11,"F5RRS":10,"OE6TZE":10,"UD4FD":9,"DL1RNN":9,"DK3UA":4,"G0LUJ":3,"DK9IP":2}},
            "IN3IYD":{"dxcall":"IN3IYD","freq":"7 024.1","mode":"CW","age":50,"lsn":{"OH6BG":35,"F6IIT":34,"HA1VHF":29,"DL3KR":26,"DL8TG":20,"DL9GTB":19,"HA2KSD":19,"S50ARX":17,"SV1CDN":16,"HB9BXE":16,"OL7M":16,"DO4DXA":12,"F4EGZ":11,"HB9JCB":11,"OE6TZE":10,"F5RRS":10,"DL1RNN":9,"UD4FD":9,"DK3UA":4,"G0LUJ":3,"DK9IP":2}},
            "PA3GEG":{"dxcall":"PA3GEG","freq":"14 028.0","mode":"CW","age":50,"lsn":{"F6IIT":34,"S50ARX":21,"OL7M":16,"HA2KSD":7,"OE6TZE":5,"HB9DCO":5,"DK3UA":4,"CT1BOH":15}},"F5HTR\/P":{"dxcall":"F5HTR\/P","freq":"7 032.0","mode":"CW","age":58,"lsn":{"F6IIT":34,"S50ARX":21,"OL7M":16,"HA2KSD":7,"DK0TE":5,"HB9DCO":5,"OE6TZE":22,"DK3UA":4}},
            "EM5SE":{"dxcall":"EM5SE","freq":"7 044.8","mode":"CW","age":58,"lsn":{"F6IIT":34,"S50ARX":21,"OL7M":16,"HA2KSD":7,"DK0TE":5,"HB9DCO":28,"OE6TZE":22,"DK3UA":4}}
            }
        

with &xml=1 e.g. https://www.hamqth.com/rbn_data.php?data=1&band=160,80,60,40,30,20,17,15,12,10,6,2&fromcont=EU&mode=CW,RTTY,PSK31,PSK63&cont=AF,AN,AS,EU,NA,SA,OC&waz=*&itu=*&age=60&order=3&xml=1
returns:

    <?xml version="1.0"?>
    <rbnspots>
        <rbnspot>
            <dxcall>W3KHG</dxcall>
            <freq>7007.2</freq>
            <age>1</age>
            <reports>
                <report>
                    <call>GW8IZR</call>
                    <snr>10</snr>
                </report>
                <report>
                    <call>G0LUJ</call>
                    <snr>8</snr>
                </report>
            </reports>
        </rbnspot>
        <rbnspot>
            <dxcall>PE3RKE</dxcall>
            <freq>7023.0</freq>
            <age>1</age>
            <reports>
                <report>
                    <call>GW8IZR</call>
                    <snr>10</snr>
                </report>
                <report>
                    <call>OL7M</call>
                    <snr>14</snr>
                </report>
            </reports>
        </rbnspot>
    </rbnspots>
    
This API is also unlimited and should be very fast. All RBN spots newer than one hour are stored in memory table.

If you find any bug or have any problem with developer's interface, please let me know via support@hamqth.com. Everything is provided for free, but please put HamQTH banner on your page, tell your friends about us, or consider small donation. Thank you!

Changelog

2.8 - (22 Sep 2018) picture tag returned, returns link to user header image
2.7 - (21 Dec 2017) added RBN data in JSON or XML, documentation updated
2.6 - (28 Jan 2015) added qslrdirect field, documentation updated
2.5 - (11 Jan 2015) removed self spot interface, added country name and band to CSV dxcluster spots
2.4 - (29 Jun 2014) added JSON DXCC search
2.3 - (25 jun 2013) added Simple award verification protocol
2.2 - (12 may 2013) added self spotting inteface
2.1 - (10 may 2013) added dxcluster inteface
2.0 - (20 feb 2013) added social network fields
1.9 - (18 nov 2012) real-time QSO upload interface added
1.8 - (29 sep 2012) added access to bio information through XML interface
1.7 - (02 sep 2012) added log upload interface
1.6 - (28 jun 2012) added ADR and ADR_ADIF fields
1.5 - (22 apr 2012) added XML DXCC search
1.4 - (02 mar 2012) added latitude, longitude, utc_offset and continent fields
1.3 - (07 oct 2011) added prg parameter into XML search query
1.2 - (26 sep 2011) added country and adr_country fields
1.1 - (01 sep 2011) added IOTA field