PHPackages                             long-blade/gisis-ships-sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. long-blade/gisis-ships-sdk

ActiveLibrary[API Development](/categories/api)

long-blade/gisis-ships-sdk
==========================

PHP SDK for searching the IMO GISIS public Ships database (IMO number / ship name lookups) over an authenticated browser session.

v0.2.0(today)01↑2900%MITPHPPHP &gt;=8.2

Since Jun 19Pushed todayCompare

[ Source](https://github.com/long-blade/gisis-ships-sdk)[ Packagist](https://packagist.org/packages/long-blade/gisis-ships-sdk)[ RSS](/packages/long-blade-gisis-ships-sdk/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (8)Versions (3)Used By (0)

gisis-ships
===========

[](#gisis-ships)

A PHP SDK for querying the **IMO GISIS public Ships database**([gisis.imo.org](https://gisis.imo.org/Public/SHIPS/Default.aspx)) — look up vessels by **IMO number**, **ship name**, **call sign** or **MMSI** and get back clean, typed `Ship` objects.

It also ships a fully offline **IMO check-digit validator**, so you can validate a number's format without any network call.

---

Table of contents
-----------------

[](#table-of-contents)

- [How authentication works (read this first)](#how-authentication-works-read-this-first)
- [Requirements](#requirements)
- [Installation](#installation)
- [Getting your session cookie](#getting-your-session-cookie)
- [Quick start](#quick-start)
- [Laravel](#laravel)
- [Searching](#searching)
- [The `Ship` model](#the-ship-model)
- [Offline IMO validation](#offline-imo-validation)
- [Error handling](#error-handling)
- [How it works under the hood](#how-it-works-under-the-hood)
- [Development](#development)
- [Legal &amp; fair use](#legal--fair-use)
- [Roadmap](#roadmap)
- [Versioning](#versioning)
- [License](#license)

---

How authentication works (read this first)
------------------------------------------

[](#how-authentication-works-read-this-first)

GISIS sign-in goes through `webaccounts.imo.org`, which is protected by **Cloudflare Turnstile** plus a multi-step username/password flow. That challenge is designed to stop headless automation, and **this SDK does not automate or bypass it.**

Instead it uses a **human-in-the-loop session model**:

1. You log in once in a real browser (you solve Turnstile + password).
2. You copy the resulting **`IMOWEBACC`** session cookie into the SDK (via `.env`or directly in code).
3. The SDK reuses that authenticated session to run searches and parse results.

When the session expires, log in again and refresh the cookie. This is the only approach that is both reliable and respectful of the site's access controls — keep request volume modest and cache results.

---

Requirements
------------

[](#requirements)

- PHP **8.2+** with `ext-json`
- [Composer](https://getcomposer.org/)
- A free GISIS public account

---

Installation
------------

[](#installation)

```
composer require long-blade/gisis-ships-sdk
```

Or clone and install dev dependencies to hack on it:

```
git clone git@github.com:long-blade/gisis-ships-sdk.git
cd gisis-ships-sdk
composer install
```

---

Getting your session cookie
---------------------------

[](#getting-your-session-cookie)

1. Log in at  in your browser.
2. Open **DevTools → Application/Storage → Cookies → `gisis.imo.org`**.
3. Copy the value of the **`IMOWEBACC`** cookie.
4. Put it in a `.env` file (copy `.env.example`):

```
GISIS_IMOWEBACC=PASTE_THE_LONG_HEX_VALUE_HERE
# Optional — helps stick to the same backend node:
GISIS_ARRAFFINITY=
GISIS_ASPNET_SESSIONID=
```

> 🔒 `.env` is gitignored. Never commit your cookie — it is a live session token.

---

Quick start
-----------

[](#quick-start)

```
require 'vendor/autoload.php';

use Mavroforakis\Gisis\Auth\CookieSessionProvider;
use Mavroforakis\Gisis\GisisShips;

$session = new CookieSessionProvider([
    'IMOWEBACC' => getenv('GISIS_IMOWEBACC'),
]);

$gisis = new GisisShips($session);

$ship = $gisis->findByImo('9074729');

echo $ship?->name;            // KAVITA
echo $ship?->flag;            // Palau
echo $ship?->registeredOwner; // CASSINI SHIP OWNING CO
```

You can also build the session from a raw cookie header copied out of DevTools:

```
$session = CookieSessionProvider::fromCookieHeader(
    'ARRAffinity=...; ASP.NET_SessionId=...; IMOWEBACC=...'
);
```

### CLI demo

[](#cli-demo)

```
php examples/lookup.php 9074729
php examples/lookup.php --name "EVER GIVEN"
```

---

Laravel
-------

[](#laravel)

The package ships a Laravel integration that is **auto-discovered** — no manual provider or alias registration needed.

**1. Install**

```
composer require long-blade/gisis-ships-sdk
```

**2. Add the session cookie to your app's `.env`**

```
GISIS_IMOWEBACC=PASTE_THE_LONG_HEX_VALUE_HERE
GISIS_ARRAFFINITY=
GISIS_ASPNET_SESSIONID=
```

These map to `config/gisis.php`. To customise the config, publish it:

```
php artisan vendor:publish --tag=gisis-config
```

**3. Use it** — resolve from the container (constructor injection) …

```
use Mavroforakis\Gisis\GisisShips;

class VesselController
{
    public function show(GisisShips $gisis, string $imo)
    {
        return response()->json($gisis->findByImo($imo)?->toArray());
    }
}
```

… or via the `Gisis` facade:

```
use Mavroforakis\Gisis\Laravel\Gisis;

$ship    = Gisis::findByImo('9074729');
$matches = Gisis::findByName('EVER GIVEN');
```

> The `GisisShips` binding is a lazy singleton: the cookie is only read when you first resolve it, so a missing/expired cookie surfaces as an `AuthenticationException` at call time (not at boot). Handle it and prompt for a refreshed `GISIS_IMOWEBACC`.

> ℹ️ Don't call `env()` directly in app code — these values come through `config('gisis.*')`, which is safe under `php artisan config:cache`.

---

Searching
---------

[](#searching)

### Exact IMO lookup

[](#exact-imo-lookup)

`findByImo()` validates the number's check digit **locally first** (no wasted request on malformed input), then returns a single `?Ship`:

```
$ship = $gisis->findByImo('IMO 9074729'); // "IMO" prefix & spacing are normalised
```

### By name (partial match)

[](#by-name-partial-match)

```
/** @var list $ships */
$ships = $gisis->findByName('EVER GIVEN');
```

### Arbitrary conditions (the where-builder)

[](#arbitrary-conditions-the-where-builder)

GISIS searches are driven by typed conditions. Compose them directly:

```
use Mavroforakis\Gisis\Search\Condition;

$ships = $gisis->search(
    Condition::nameContains('MAERSK'),
    Condition::callSignIs('OXOM2'),
);
```

Available condition helpers:

HelperFieldOperator`Condition::imoIs($imo)`IMO Number`imoNumber_is``Condition::nameContains($name)`Ship name`name_contains``Condition::callSignIs($cs)`Call sign`name_is``Condition::mmsiIs($mmsi)`MMSI`name_is`Need another field/operator combination? Construct a `Condition` directly with a `ShipField` and a valid operator string (see `ShipField` for the field/operator map; invalid pairings throw before any request is made):

```
use Mavroforakis\Gisis\Search\{Condition, ShipField};

$ships = $gisis->search(new Condition(ShipField::ShipName, 'name_startswith', 'EVER'));
```

---

The `Ship` model
----------------

[](#the-ship-model)

`Mavroforakis\Gisis\Model\Ship` is an immutable value object. Fields are nullable because GISIS does not populate every column in every view.

```
$ship->imoNumber;        // "9074729" (stamped on findByImo results)
$ship->name;             // "KAVITA"
$ship->flag;             // "Palau"
$ship->grossTonnage;     // "15,899"
$ship->shipType;         // "General Cargo Ship (General Cargo)"
$ship->yearOfBuild;      // "1995"
$ship->registeredOwner;  // "CASSINI SHIP OWNING CO"
$ship->extra;            // ['registeredOwnerImoCompany' => '6277131', 'detailPostbackArgument' => '_rc0']

$ship->toArray();        // everything as an array (handy for JSON)
```

---

Offline IMO validation
----------------------

[](#offline-imo-validation)

No session required — pure check-digit math:

```
use Mavroforakis\Gisis\Imo\ImoNumber;

ImoNumber::isValid('9074729');        // true
ImoNumber::isValid('9074728');        // false (bad check digit)
ImoNumber::normalize('IMO 9074729');  // "9074729"

$imo = ImoNumber::fromString('IMO 9074729'); // throws InvalidImoNumberException if invalid
(string) $imo;                               // "9074729"
```

---

Error handling
--------------

[](#error-handling)

All exceptions extend `Mavroforakis\Gisis\Exception\GisisException`:

ExceptionWhen`InvalidImoNumberException`The IMO number fails local validation.`AuthenticationException`Missing cookie, or the session expired and GISIS bounced us to the login/Turnstile page. Re-login and refresh `IMOWEBACC`.`GisisException`Network/transport errors and other failures.```
use Mavroforakis\Gisis\Exception\AuthenticationException;

try {
    $ship = $gisis->findByImo('9074729');
} catch (AuthenticationException $e) {
    // prompt the user to refresh their cookie
}
```

---

How it works under the hood
---------------------------

[](#how-it-works-under-the-hood)

`gisis.imo.org` is an ASP.NET WebForms application, so the SDK:

1. **GETs** `ShipSearch.aspx` to read the per-session hidden state (`__VIEWSTATE`, `__EVENTVALIDATION`, …) — these are not reusable, so every search fetches fresh ones.
2. **POSTs** the search as a WebForms postback (`__EVENTTARGET` = the search button) with the query encoded as the where-builder's `conditionsXml` (a double-URL-encoded XML fragment).
3. **Parses** the results grid (`#…_gvShip`) into `Ship` objects.

The expired-session guard inspects redirects and page markers (`WebLogin.aspx`, `turnstile`) and raises `AuthenticationException` instead of returning garbage.

---

Development
-----------

[](#development)

```
composer install
./vendor/bin/phpunit        # run the test suite
```

Parser tests run against a saved HTML fixture (`tests/fixtures/`), so they need no live session. The IMO validator is fully unit-tested.

---

Legal &amp; fair use
--------------------

[](#legal--fair-use)

This SDK automates **your own authenticated browser session** against a public registry, at human-scale volume. It is intended for legitimate, occasional vessel verification. You are responsible for complying with IMO/GISIS terms of use — do not bulk-scrape, redistribute datasets, or hammer the service. For high-volume or commercial needs, use a dedicated maritime data provider.

---

Roadmap
-------

[](#roadmap)

- Ship **detail** page (call sign, MMSI, dimensions, former names) via the per-row postback already captured in `extra.detailPostbackArgument`.
- Pagination for large result sets.
- Optional response caching.

---

Versioning
----------

[](#versioning)

This project follows [Semantic Versioning](https://semver.org/). While on the `0.x` line, minor versions may introduce changes; pin accordingly:

```
composer require long-blade/gisis-ships-sdk:^0.2
```

See [CHANGELOG.md](CHANGELOG.md) for the release history. New releases are cut by tagging:

```
git tag -a v0.3.0 -m "..." && git push origin v0.3.0
```

---

License
-------

[](#license)

MIT

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance100

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

0d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/11339340?v=4)[Michael. M](/maintainers/long-blade)[@long-blade](https://github.com/long-blade)

---

Top Contributors

[![long-blade](https://avatars.githubusercontent.com/u/11339340?v=4)](https://github.com/long-blade "long-blade (3 commits)")

---

Tags

sdkIMOgisisshipsvesselmaritime

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/long-blade-gisis-ships-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/long-blade-gisis-ships-sdk/health.svg)](https://phpackages.com/packages/long-blade-gisis-ships-sdk)
```

###  Alternatives

[craftcms/cms

Craft CMS

3.6k3.6M2.9k](/packages/craftcms-cms)[aws/aws-sdk-php

AWS SDK for PHP - Use Amazon Web Services in your PHP project

6.2k532.1M2.5k](/packages/aws-aws-sdk-php)[tencentcloud/tencentcloud-sdk-php

TencentCloudApi php sdk

3661.2M46](/packages/tencentcloud-tencentcloud-sdk-php)[sproutcms/cms

Enterprise content management and framework

242.2k4](/packages/sproutcms-cms)[eslazarev/wildberries-sdk

Wildberries OpenAPI clients (generated).

232.5k](/packages/eslazarev-wildberries-sdk)[files.com/files-php-sdk

Files.com PHP SDK

2478.1k](/packages/filescom-files-php-sdk)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
