NAME
Geo::What3Words - turn WGS84 coordinates into three word addresses and vice-versa using what3words.com HTTPS API
VERSION
version 3.0.6
SYNOPSIS
my $w3w = Geo::What3Words->new( key => 'your-api-key' );
$w3w->pos2words('51.484463,-0.195405');
# returns 'prom.cape.pump'
$w3w->pos2words('51.484463,-0.195405', 'ru');
# returns 'питомец.шутить.намеренно'
$w3w->words2pos('prom.cape.pump');
# returns '51.484463,-0.195405' (latitude,longitude)
DESCRIPTION
what3words (https://what3words.com/) divides the world into 57 trillion squares of 3 metres x 3 metres. Each square has been given a 3 word address comprised of 3 words from the dictionary.
This module calls API version 3 (https://docs.what3words.com/public-api/) to convert coordinates into 3 word addresses (forward) and 3 words into coordinates (reverse).
Versions 1 and 2 are deprecated and are no longer supported.
You need to sign up at https://what3words.com/login and then register for an API key at https://developer.what3words.com
METHODS
new
Creates a new instance. The key parameter is required.
my $w3w = Geo::What3Words->new( key => 'your-api-key' );
my $w3w = Geo::What3Words->new( key => 'your-api-key', language => 'ru' );
Options:
- key (required)
-
Your what3words API key.
- language
-
Default language for 3 word addresses (e.g.
'ru','de'). Can be overridden per request. - api_endpoint
-
Override the API URL. Defaults to
https://api.what3words.com/v3/. Useful when testing self-hosted installations.Warning: Set the value carefully, and not from user-supplied data, otherwise all data including the API key could be sent to an untrusted endpoint.
- ua
-
Provide your own HTTP::Tiny instance, e.g. for proxy configuration or testing.
- logging
-
For debugging you can either set logging to a true value or provide a callback.
my $w3w = Geo::What3Words->new( key => 'your-api-key', logging => 1 ); # will print debugging output to STDOUT my $callback = sub { my $msg = shift; $my_log4perl_logger->info($msg) }; my $w3w = Geo::What3Words->new( key => 'your-api-key', logging => $callback ); # will log with log4perl
Create one instance and reuse it for all your requests. HTTP::Tiny keeps the connection to the API open between requests, so only the first request pays for the TLS handshake. Creating a new instance per request loses that.
ping
Check if the remote server is available. This is helpful for debugging or testing, but too slow to run for every conversion.
$w3w->ping();
words2pos
Convenience wrapper around words_to_position. Takes a 3 word address string, returns a string 'latitude,longitude' or undef on failure.
$w3w->words2pos('prom.cape.pump');
# returns '51.484463,-0.195405'
$w3w->words2pos('does.not.exist');
# returns undef
pos2words
Convenience wrapper around position_to_words. Takes a string 'latitude,longitude' and an optional language code. Returns a 3 word address string or undef on failure.
$w3w->pos2words('51.484463,-0.195405');
# returns 'prom.cape.pump'
$w3w->pos2words('51.484463,-0.195405', 'ru');
# returns 'питомец.шутить.намеренно'
$w3w->pos2words('invalid,coords');
# returns undef
valid_words_format
Returns 1 if the string looks like three dot-separated words, 0 otherwise. Supports Unicode (e.g. Cyrillic, Turkish). Does not call the remote API.
$w3w->valid_words_format('prom.cape.pump');
# returns 1
$w3w->valid_words_format('диета.новшество.компаньон');
# returns 1
$w3w->valid_words_format('Not.Valid.Format');
# returns 0 (uppercase letters)
words_to_position
Takes a 3 word address string and returns a hashref with coordinates, country, language, map link, nearest place, and bounding square. Returns undef on failure.
$w3w->words_to_position('prom.cape.pump');
# {
# 'coordinates' => {
# 'lat' => '51.484463',
# 'lng' => '-0.195405'
# },
# 'country' => 'GB',
# 'language' => 'en',
# 'map' => 'https://w3w.co/prom.cape.pump',
# 'nearestPlace' => 'Kensington, London',
# 'square' => {
# 'northeast' => {
# 'lat' => '51.484476',
# 'lng' => '-0.195383'
# },
# 'southwest' => {
# 'lat' => '51.484449',
# 'lng' => '-0.195426'
# }
# },
# 'words' => 'prom.cape.pump'
# };
position_to_words
Takes a string 'latitude,longitude' and an optional language code. Returns a hashref with coordinates, country, language, map link, nearest place, and bounding square. Returns undef on failure.
$w3w->position_to_words('51.484463,-0.195405');
$w3w->position_to_words('51.484463,-0.195405', 'ru');
# {
# 'coordinates' => {
# 'lat' => '51.484463',
# 'lng' => '-0.195405'
# },
# 'country' => 'GB',
# 'language' => 'en',
# 'map' => 'https://w3w.co/prom.cape.pump',
# 'nearestPlace' => 'Kensington, London',
# 'square' => {
# 'northeast' => {
# 'lat' => '51.484476',
# 'lng' => '-0.195383'
# },
# 'southwest' => {
# 'lat' => '51.484449',
# 'lng' => '-0.195426'
# }
# },
# 'words' => 'prom.cape.pump'
# };
get_languages
Returns a hashref containing a list of supported language codes and names.
$w3w->get_languages();
# {
# 'languages' => [
# {
# 'name' => 'German',
# 'nativeName' => 'Deutsch',
# 'code' => 'de'
# },
# {
# 'name' => 'English',
# 'nativeName' => 'English',
# 'code' => 'en'
# },
# {
# 'name' => "Spanish",
# 'nativeName' => "Español",
# 'code' => 'es'
# },
# ...
error
Returns details about why the last conversion or get_languages call failed, or undef if it succeeded.
my $words = $w3w->pos2words('51.484463,-0.195405');
if (!defined($words)) {
my $error = $w3w->error;
# {
# status => 401,
# code => 'InvalidKey',
# message => 'Authentication failed; invalid API key'
# }
}
status is the HTTP status code. code and message come from the API, see https://developer.what3words.com/public-api/docs.
If the input was rejected before calling the API status is undef and code is BadWords or BadCoordinates. If the API could not be reached status is 599, code is undef and message is the error from HTTP::Tiny.
oneword_available
Deprecated. Calling this method will emit a warning and return undef.
ERROR HANDLING
On HTTP errors or invalid input the convenience methods (pos2words, words2pos) return undef. The verbose methods (position_to_words, words_to_position, get_languages) also return undef on failure.
In all cases a warning is emitted via warn with the HTTP status code. You can catch these with $SIG{__WARN__} or Test::Warn in tests.
error returns the details of the last failure, including the error code and message from the API.
Input that is clearly invalid is rejected before calling the API, also with a warning: a 3 word address that isn't three dot-separated words, or coordinates that aren't 'latitude,longitude' with latitude between -90 and 90 and longitude between -180 and 180.
TESTING
The test suite uses pre-recorded API responses. If you suspect something changed in the API you can force the test suite to use live requests with your API key:
W3W_API_KEY=<your key> prove -l t/base.t
The recorded responses are in t/data/responses. To update them, run the tests against the live API with recording switched on. Your API key is not saved in the recorded responses.
W3W_API_KEY=<your key> W3W_RECORD=1 prove -l t/base.t
Set W3W_API_ENDPOINT to run the live or recording tests against another server, e.g. a self-hosted installation.
The code style tests only run with AUTHOR_TESTING set, as dzil test --author does.
SEE ALSO
https://what3words.com/ - what3words website
https://developer.what3words.com - API documentation and key registration
https://developer.what3words.com/public-api/docs - API v3 reference
AUTHOR
mtmail <mtmail-cpan@gmx.net>
COPYRIGHT AND LICENSE
This software is copyright (c) 2026 by OpenCage GmbH.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.