Related Commercial Information: Live ADS-B Flight Data Feed (Worldwide)

FlightAware Firehose API Documentation

Purpose

Firehose is a FlightAware API for receiving streaming flight positions (e.g., RADAR, ADS-B, Mode S multilateration (MLAT), datalink, etc) as well as flight status data (e.g., flight plans, departure/arrival messages, flight updates) and surface movement positions. This page defines a protocol for establishing a connection and receiving data from the Firehose interface.

If you have a question that is not answered by this document, please check our freqently asked questions to see if your topic has already been answered there before contacting your account representative for support.

Connection Protocol

All requests must include a username and FlightXML API Key (don't have one?). In addition to obtaining an API Key, the user's account must be specially enabled by a FlightAware representative for access to the firehose service.

If you have a firewall that needs authorization, then please authorize both of the ranges:

  • 70.42.6.128/25
  • 206.123.125.0/25

A customer's application will connect via a TCP socket secured with Secure Socket Layer/Transport Layer Security (SSL/TLS) protocol to FlightAware. The port for downlink connections will be 1501. The hostname will be firehose.flightaware.com, unless FlightAware has instructed the customer otherwise.

On the downlink connection customer's application will send an initiation command followed by a newline character, to specify the credentials, time range, and any filtering of messages to be provided, and both sides will keep the connection open indefinitely for FlightAware to send messages to the customer as they become available. If an error in the syntax or credentials of the initiation command occurs, the firehose server will transmit an error message and disconnect.

The customer's application should be designed to detect socket disconnection and attempt to reconnect to the FlightAware server when necessary. It is also recommended to have an idle connection handler that will disconnect and reconnect if no messages have been received in the last 5 minutes. When reconnecting to the FlightAware server, the "pitr" or "range" initiation command can be used to resume playback from the pitr timestamp of the last received message, if desired.

Testing Connectivity

An important initial diagnostic technique is to confirm your outbound network connectivity over the necessary port number. For testing and development purposes, the OpenSSL command-line tools can be used to check the ability to open a SSL/TLS connection to FlightAware:

openssl s_client -host firehose.flightaware.com -port 1501 -tls1

If the connection is successfully established, OpenSSL will display the server's certificate information and then pause. Should it fail to connect, contact your network administrator to ensure that your application server has access to make outbound TCP connections on port 1501 to the FlightAware datacenter.

Initiation Command Syntax

Initiation Command Options

  • Required
    • username <argument> - Supply the credentials for authentication. This should be the username of the FlightAware account that has been granted access.
    • password <argument> - Supply the credentials for authentication. In most cases, this should actually be the FlightXML API Key and not the password of the account.
    • the following time range options are mutually exclusive; only one may be used in an initiation command.
      • live - Request live data from the present time forward.
      • pitr <epoch> - Request data from a specified time, in POSIX epoch format, in the past until the current time, and continue with the live behavior.
      • range <start epoch> <end epoch> - Send data between two specified times, in POSIX epoch format. FlightAware will disconnect the connection when last message has been sent.
  • Optional
    • filter "<airline code list>" - Send flight information only related to the listed airlines. The list is a series of space separated ICAO airline codes wrapped in double quotes. For example: filter "FIN" or filter "FIN BAW AAL".
    • idents "<ident reg list>" - Send flight information only related to the listed idents or aircraft registration/tails. The list is a series of space separated idents or registrations wrapped in double quotes, optionally using wildcard patterns. For example: idents "N1234 N2345 N456 CXYZA" or idents "N1*UA N2*UA UAL12 UAL34".
    • version <version number> - Protocol version the client expects. The latest version is assumed if this is not specified.
    • format <format type> - Specifies the output mode of the responses. At this time, "json" is the only supported format, however other formats including "csv", "tsv", "xml" may be offered in the future. If format is not specified, then "json" is assumed.
    • events "<event code list>" - Specifies a list of which downlink messages should be sent. The available event codes include: flightplan, departure, arrival, cancellation, position, offblock, onblock, ground_position, vehicle_position. This argument may be a list of space separated terms wrapped in double quotes. For example: events "flightplan departure arrival" or events "position".
    • latlong "<lowLat> <lowLon> <hiLat> <hiLon>" - Specifies that only positions within the specified rectangle should be sent and any others will be ignored, unless the flight has already been matched by other criteria. For example: latlong "29 -95 30 -94". This command may be repeated multiple times in a single initiation command, allowing positions within any of the specified rectangles to be matched.
    • airport_filter "<airport pattern list>" - Send flight information only for flights originating from or destined for airports matching the space separated list of glob patterns provided. For example: airport_filter "CYUL" or airport_filter "K??? P??? TJSJ".
    • compression <mode> - Requests that the server response should use data compression to reduce network bandwidth. The initiation command sent to the server must not be compressed. The mode argument indicates the compression algorithm and must be "gzip", "compress", or "deflate". For example: compression gzip.
    • keepalive <interval> - Requests that the server should periodically send a "keepalive" message at the specified interval, measured in whole integer seconds (must be 15 seconds or greater). The keepalive messages contain the current timestamp on the server and the pitr timestamp within the data stream. This can be especially useful for feeds that are very low data volume due to heavy filtering, where it may be difficult to distinguish between a failed network connection and a period of time with few aircraft events. For example: keepalive 60.

    Example downlink initiation commands:

    • live filter "BAW" version 6.0 username james password 1234abcd
    • range 1377204966 1377214966 filter "AAL BAW FIN" username joe password 34567abdef
    • pitr 13772104996 username andrew password bcdef1235
    • live version 5.0 user mary password 123abc events "position"
    • live version 6.0 username daniel password abcd1234 events "position" latlong "29 -95 30 -94"
    • live version 8.0 username alonzo password abcd1234 events "ground_position vehicle_position" airport_filter "KBOS"

Keeping a Persistent Connection

  • Network connectivity for long-lived network connections over the internet are not always reliable and will tend to stall or hang occasionally, beyond our control. Additionally, we can occasionally have internal network connections that might disrupt communications between our Firehose server and the internal messaging bus that might also cause this type of condition. Very long-lived Firehose connections do eventually need to be disconnected by our server-side (system updates, feed maintenance, resource leaks), but that condition should result in a "connection closed by peer" rather than a "series of end of lines". Be sure that your application has logic to handle the condition of the connection being actively closed by the server.
  • Keeping a persistent connection open is the expected use-case. We also recommend disconnecting and reconnecting if you receive no data after an extended period of time. When reconnecting, using the "pitr" command to resume data from the timestamp that you last received is recommended.
  • The maximum number of allowable connections for Firehose is two per user account. One connection is suggested for your production environment and one connection for your development environment. Additional connection licenses are available.

Notes

  • Times are specified as POSIX time also known as UNIX epoch format. Specifically, the number of seconds since 00:00:00 UTC on 1 January 1970. If subsecond resolution is available, the time can be specified floating point. Otherwise the value should be an integer. For example, 1375117735.797 is Monday 29 July 2013 17:08:55.797.
  • All messages sent by FlightAware on the downlink will be JavaScript Object Notation (JSON) encoded and the character encoding will be plain ASCII. The expected downlink message volume is approximately 1 Mb/s average with typical peaks of 4 Mb/s for a full feed, but this will vary depending on the type of events and filtering being requested.
  • The latency of the connection can be monitored by comparing the difference between "pitr" value and your system's current UTC time. When your application is caught up and following live data, the difference should generally be less than 15 seconds. If you observe that the difference continues to increase rather than decrease and remain less than 15, then that is an indication that your application is not able to process the datafeed quickly enough and you need to investigate ways of improving its performance.
  • When requesting surface movement (ground_position or vehicle_position) messages, you will be prevented from also requesting any non-surface messages in the same initiation command. If you are developing an application that requires the ability to receive both types of messages simultaneously, you will currently need to open two separate Firehose connections and fuse the data within your application.
  • For technical/commercial support for Firehose, please contact Max Tribolet (email).

Access Levels

Your access level will consist of any combination of the following data layers:

  1. ADS-B: Worldwide
    1. [Position message]
  2. MLAT: Worldwide
    1. [Position message]
  3. RADAR: USA, Canada, New Zealand, *Australia, Belize, Costa Rica, El Salvador, Guatamala, Honduras, Nicaragua
    1. [Position message]
  4. Transoceanic/ACARS/Estimated: Worldwide
    1. [Position message]
  5. FLIFO (Flight Status): Worldwide
    1. [Flightplan, Departure, Arrival, and Cancellation messages]
  6. Block Events: Worldwide
    1. [Offblock and Onblock messages]
  7. Surface Movement: Most major USA airports (ASDE-X and ADS-B), Worldwide (ADS-B only)
    1. [Ground_position and Vehicle_position messages]

Please ask a FlightAware representative if you would like access to additional data layers. Firehose is billed at a monthly rate for unlimited use, dependent on what data layers you choose to access and the scope of how you repurpose/redistribute the data within your application. Discounts are available for long-term commitment, up-front payment, and/or public attribution to FlightAware.

Firehose can also be used in conjunction with FlightAware Global for added satellite uplinks and EUROCONTROL data. Other aircraft operator's data can be integrated as well: read about Improving Tracking of Your Flights on FlightAware.

*Australia RADAR and ADS-B is only available for internal consumption (e.g., not for redistribution to third parties beyond yourself).

Data Coverage

For more information on FlightAware's position data coverage, please see FlightAware's coverage map.

Downlink Messages

Messages have three categories of data fields, "Mandatory", "Common", "Optional":

  • Mandatory fields must be included in every message.
  • Common fields are typically present and assist in matching messages to a particular flight or providing additional details, but are not required.
  • Optional fields are not provided by most sources, but provide important additional information to improve the quality of flight tracking.

Revision History and Version

  • Version 1.0 - Initial release
  • Version 2.0 - Lat/lon and waypoints are truncated to 5 digits of decimal precision
  • Version 3.0 - Adds squawk attribute
  • Version 4.0 - Adds hexid attribute
  • Version 5.0 (August 2015)
    • add airport_filter command to match origin/destination
    • add support for multiple latlon boxes
    • make successful latlon matches trigger matching for further messages from that same flight_id
    • make expression matching use logical-OR when multiple are specified
    • add facility_hash/facility_name to JSON messages.
    • increase maximum initiation command length to 5120
    • add command aliases for "latlon vs latlong" and "filter vs airline_filter"
  • Version 6.0 (February 2016)
    • add "pitr" element to all messages, for use with resuming via the "pitr" (point in time recovery) initiation command
    • add "fdt" (filed departure time) element to flightplan messages
  • Version 7.0 (June 2016)
    • add "compression" command to allow streamed responses to use data compression, useful for lower-bandwidth connections.
    • add support for "onblock" and "offblock" events, approved users only.
    • add support for "positions" from MLAT sources (updateType = "M"), approved users only.
    • add support for datalink sources (updateType = "D"), approved users only.
    • fields with blank values will now be omitted.
    • flight "id" (faFlightID) field now omits the colon and fork identifier suffix.
    • add support for receiving data on blocked aircraft, for customers with FlightAware Global accounts.
  • Version 8.0 (February 13, 2017)
    • add surface movement support by adding new "ground_position" and "vehicle_position" message types (updateType = "X" or updateType = "A"), approved users only.
    • add support for receiving obfuscated data on blocked aircraft, approved users only.
    • add "keepalive" command to allow periodic heartbeat/progress messages to be transmitted, useful when requesting very specific filters that produce low-traffic volume.

Firehose Examples

Java

Show example with google-gson parsing...

Requirements
  • Java SE 8
  • JSON parsing library

Depending on Java platform used, there may or may not be a standard JSON parsing library. However, there are plenty of libraries to choose from json.org.

This example uses the google-gson library. Download google-gson library from github.com.

What to change

Substitute your actual username and API key in the initiation_command.

Change/remove limit on the number of messages received.


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import javax.net.ssl.*;
import com.google.gson.Gson;

public class SSL_Client_gson {

    // substitute your own username and password
    private static String initiation_command = "live username XXXXXXXX password XXXXXXXXXXXXXXXXXXXX";
    private SSLSocket ssl_socket;
    private static final boolean useCompression = false;

    public static void main(String[] args) {
        String machineName = "firehose.flightaware.com";
        RunClient(machineName);
        System.out.println(" Thank you for using FlightAware ... bye now");
    }

    private class FlightObject {

        //define here all fields of interest from the received messages
        public String type;
        public String ident;
        public String air_ground;
        public String alt;
        public String clock;
        public String id;
        public String gs;
        public String heading;
        public String lat;
        public String lon;
        public String reg;
        public String squawk;
        public String updateType;

        @Override
        public String toString() {
            String result;
            //if any field is missing in the received message,
            //for eg if "squawk" is missing then squawk value will be null!
            //format as a table left justified, 10 chars min width
            result = String.format("%-10s %-10s\n %-10s %-10s\n %-10s %-10s\n "
                    + "%-10s %-10s\n %-10s %-10s\n %-10s %-10s\n "
                    + "%-10s %-10s\n %-10s %-10s\n %-10s %-10s\n "
                    + "%-10s %-10s\n %-10s %-10s\n %-10s %-10s\n "
                    + "%-10s %-10s\n",
                    "type", type,
                    "ident", ident,
                    "airground", air_ground,
                    "alt", alt,
                    "clock", clock,
                    "id", id,
                    "gs", gs,
                    "heading", heading,
                    "lat", lat,
                    "lon", lon,
                    "reg", reg,
                    "squawk", squawk,
                    "updateType", updateType
            );
            return result;
        }
    }

    public static void RunClient(String machineName) {
        System.out.println(" Running Client");
        try {
            SSLSocket ssl_socket;
            ssl_socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(machineName, 1501);
            // enable certifcate validation:
            SSLParameters sslParams = new SSLParameters();
            sslParams.setEndpointIdentificationAlgorithm("HTTPS");
            ssl_socket.setSSLParameters(sslParams);

            if (useCompression) {
                initiation_command += " compression gzip";
            }
            
            initiation_command += "\n";

            //send your initiation command
            OutputStreamWriter writer = new OutputStreamWriter(ssl_socket.getOutputStream(), "UTF8");
            writer.write(initiation_command);
            writer.flush();

            InputStream inputStream = ssl_socket.getInputStream();
            if (useCompression) {
                inputStream = new java.util.zip.GZIPInputStream(inputStream);
            }

            // read messages from FlightAware
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            Gson gson = new Gson();
            String message = null;
            int limit = 10; //limit number messages for testing
            while (limit > 0 && (message = reader.readLine()) != null) {
                System.out.println("msg: " + message);
                //parse message with gson
                System.out.printf("---------------- Parsing ---------------------\n");
                FlightObject flight = gson.fromJson(message, FlightObject.class);
                System.out.println(flight);
                System.out.println("---------------------------------------------\n");
                limit--;
            }

            //done, close everything
            writer.close();
            reader.close();
            inputStream.close();
            ssl_socket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Eclipse or NetBeans IDE could make development and testing easier.

Alternatively you can run commands such as (Win32):


	 Compile:

             javac -classpath "***\gson-2.3.1.jar" SSL_Client_gson.java

	 Run:

             java -classpath "***\gson-2.3.1.jar;." SSL_Client_gson
    

What to expect



 Running Client
msg: {"type":"position","ident":"TFR52","air_ground":"A","alt":"7000","clock":"1440101019","id":"TFR52-1440084510-fds-0000:0","gs":"319","heading":"286","hexid":"C81E1C","lat":"-16.61007","lon":"145.81540","reg":"ZKTLE","squawk":"6025","updateType":"A","altChange":"C"}

--------- Parsing Results --------
 type       position  
 ident      TFR52     
 airground  A         
 alt        7000      
 clock      1440101019
 id         TFR52-1440084510-fds-0000:0
 gs         319       
 heading    286       
 lat        -16.61007 
 lon        145.81540 
 reg        ZKTLE     
 squawk     6025      
 updateType A          
---------------------------------

msg: {"type":"position","ident":"TFR52","air_ground":"A","alt":"7000","clock":"1440101019","id":"TFR52-1440084510-fds-0000","gs":"319","heading":"286","hexid":"C81E1C","lat":"-16.61007","lon":"145.81540","reg":"ZKTLE","squawk":"6025","updateType":"A","altChange":" "}

--------- Parsing Results --------
 type       position  
 ident      TFR52     
 airground  A         
 alt        7000      
 clock      1440101019
 id         TFR52-1440084510-fds-0000
 gs         319       
 heading    286       
 lat        -16.61007 
 lon        145.81540 
 reg        ZKTLE     
 squawk     6025      
 updateType A          
---------------------------------

Show example with json-simple parsing...

Requirements
  • Java SE 8
  • JSON parsing library

Depending on Java platform used, there may or may not be a standard JSON parsing library. However, there are plenty of libraries to choose from json.org.

This example uses Json-simple "a simple lightweight Java toolkit for JSON". Download Json-simple library from github.com.

What to change

Substitute your actual username and API key in the initiation_command.

Change/remove limit on the number of messages received.


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import javax.net.ssl.*;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

public class SSL_Client_json_simple {

    // substitute your own username and password
    private static String initiation_command = "live username XXXXXXXX password XXXXXXXXXXXXXXXXXXXX";
    private static final boolean useCompression = false;
    private SSLSocket ssl_socket;

    public static void main(String[] args) {
        String machineName = "firehose.flightaware.com";
        RunClient(machineName);
        System.out.println(" Thank you for using FlightAware ... bye now");
    }

    private static void RunClient(String machineName) {
        System.out.println(" Running Client");
        try {
            SSLSocket ssl_socket;
            ssl_socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(machineName, 1501);
            // enable certifcate validation:
            SSLParameters sslParams = new SSLParameters();
            sslParams.setEndpointIdentificationAlgorithm("HTTPS");
            ssl_socket.setSSLParameters(sslParams);

            if (useCompression) {
                initiation_command += " compression gzip";
            }

            initiation_command += "\n";
            
            //send your initiation command
            OutputStreamWriter writer = new OutputStreamWriter(ssl_socket.getOutputStream(), "UTF8");
            writer.write(initiation_command);
            writer.flush();

            InputStream inputStream = ssl_socket.getInputStream();
            if (useCompression) {
                inputStream = new java.util.zip.GZIPInputStream(inputStream);
            }

            // read messages from FlightAware
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            String message = null;
            int limit = 5; //limit number messages for testing
            while (limit > 0 && (message = reader.readLine()) != null) {
                System.out.println("msg: " + message + "\n");
                parse_json(message);
                limit--;
            }

            //done, close everything
            writer.close();
            reader.close();
            inputStream.close();
            ssl_socket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void parse_json(String message) {
        //using JSON.simple: Java toolkit for JSON
        JSONParser jsonParser = new JSONParser();
        JSONObject jsonObject;
        try {
            // parse message from json to JSONObject
            jsonObject = (JSONObject) jsonParser.parse(message);

            // retrieve values of interest associated with the keys
            // for alternative ways to retrieve data checks http://www.json.org/javadoc/org/json/JSONObject.html
            String type = (String) jsonObject.get("type");
            String ident = (String) jsonObject.get("ident");
            String air_ground = (String) jsonObject.get("air_ground");
            String alt = (String) jsonObject.get("alt");
            String clock = (String) jsonObject.get("clock");
            String id = (String) jsonObject.get("id");
            String gs = (String) jsonObject.get("gs");
            String heading = (String) jsonObject.get("heading");
            String lat = (String) jsonObject.get("lat");
            String lon = (String) jsonObject.get("lon");
            String reg = (String) jsonObject.get("reg");
            String squawk = (String) jsonObject.get("squawk");
            String updateType = (String) jsonObject.get("updateType");
            // if any field is missing, for eg if "squawk" is missing then squawk value will be null!

            // print values from above
            System.out.println("--------- Parsing Results --------");
            System.out.println(String.format(" %-10s %-10s\n "
                    + "%-10s %-10s\n %-10s %-10s\n %-10s %-10s\n "
                    + "%-10s %-10s\n %-10s %-10s\n %-10s %-10s\n "
                    + "%-10s %-10s\n %-10s %-10s\n %-10s %-10s\n "
                    + "%-10s %-10s\n %-10s %-10s\n %-10s %-10s ",
                    "type", type,
                    "ident", ident,
                    "airground", air_ground,
                    "alt", alt,
                    "clock", clock,
                    "id", id,
                    "gs", gs,
                    "heading", heading,
                    "lat", lat,
                    "lon", lon,
                    "reg", reg,
                    "squawk", squawk,
                    "updateType", updateType
            ));
            System.out.println("---------------------------------\n");

        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

Eclipse or NetBeans IDE could make development and testing easier.

Alternatively you can run commands such as (Win32):


        Compile:

                javac -classpath "xxx\json-simple-1.1.1.jar" SSL_Client_json_simple.java

        Run:

               java -classpath "xxx\json-simple-1.1.1.jar;." SSL_Client_json_simple
    

What to expect


 Running Client
msg: {"type":"position","ident":"VOI423","air_ground":"A","alt":"7400","clock":"1440096358","id":"VOI423-1439922000-schedule-0001","gs":"184","heading":"295","hexid":"0D081C","lat":"20.54741","lon":"-103.36899","updateType":"A","altChange":"C"}

--------- Parsing Results --------
type       position  
ident      VOI423    
airground  A         
alt        7400      
clock      1440096358
id         VOI423-1439922000-schedule-0001
gs         184       
heading    295       
lat        20.54741  
lon        -103.36899
reg        null      
squawk     null      
updateType A         
---------------------------------

msg: {"type":"position","ident":"N317SW","air_ground":"A","alt":"5600","clock":"1440096358","id":"N317SW-1440095950-adhoc-0","gs":"169","heading":"62","hexid":"A36277","lat":"41.58961","lon":"-92.50894","reg":"N317SW","squawk":"1200","updateType":"A","altChange":"C"}

--------- Parsing Results --------
type       position  
ident      N317SW    
airground  A         
alt        5600      
clock      1440096358
id         N317SW-1440095950-adhoc-0
gs         169       
heading    62        
lat        41.58961  
lon        -92.50894 
reg        N317SW    
squawk     1200      
updateType A         
---------------------------------

C#

Show example ...

Requirements

Parsing JSON in C# can be done using .NET Framework Classes or by downloading a third party library.

There are plenty of libraries to choose from json.org.

For this example we are going to use Json.NET - "a popular high-performance JSON framework for .NET". Download Json.NET from json.codeplex.com.

What to change

Substitute your actual username and API key in the initiation_command.

Change/remove limit on the number of messages received.


using System;
using System.Threading;
using System.Collections;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.IO;
using System.IO.Compression;
using Newtonsoft.Json;

namespace SSLClient
{

    public class FlightObject
    {

        public String type;
        public String ident;
        public String air_ground;
        public String alt;
        public String clock;
        public String id;
        public String gs;
        public String heading;
        public String lat;
        public String lon;
        public String reg;
        public String squawk;
        public String updateType;


        public String toString()
        {
            String result;
            // format result into 2 columns, left justify data, min 10 chars col space
            result = String.Format(" {0,-10} {1,-10}\n {2,-10} {3,-10}\n {4,-10} {5,-10}\n" +
                                   " {6,-10} {7,-10}\n {8,-10} {9,-10}\n {10,-10} {11,-10}\n" +
                                   " {12,-10} {13,-10}\n {14,-10} {15,-10}\n {16,-10} {17,-10}\n" +
                                   " {18,-10} {19,-10}\n {20,-10} {21,-10}\n {22,-10} {23,-10}\n" +
                                   " {24,-10} {25,-10}\n",
                                   "type", type,
                                   "ident", ident,
                                   "airground", air_ground,
                                   "alt", alt,
                                   "clock", clock,
                                   "id", id,
                                   "gs", gs,
                                   "heading", heading,
                                   "lat", lat,
                                   "lon", lon,
                                   "reg", reg,
                                   "squawk", squawk,
                                   "updateType", updateType
                                  );
            return result;
        }
    }


    public class SSLClient
    {
        public static String username = "XXXXXXXX";
        public static String apikey = "XXXXXXXXXXXXXXXXXXXX";
        public static Boolean useCompression = true;
        public static String initiation_command = "live username " + username + " password " + apikey +
                (useCompression ? " compression deflate" : "") + "\n";

        // The following method is invoked by the RemoteCertificateValidationDelegate
        // prevent communication with unauthenticated server
        public static bool ValidateServerCertificate(
            object sender,
            X509Certificate certificate,
            X509Chain chain,
            SslPolicyErrors sslPolicyErrors)
        {
            if (sslPolicyErrors == SslPolicyErrors.None)
            {
                // authenticated
                return true;
            }

            Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
            // Do not allow this client to communicate with unauthenticated servers.
            return false;
        }

        public static void RunClient(string machineName, string serverName)
        {
            // Create a TCP/IP client socket.
            TcpClient client = new TcpClient(machineName, 1501);

            // Create ssl stream to read data
            SslStream sslStream = new SslStream(
                client.GetStream(),
                true,
                new RemoteCertificateValidationCallback(ValidateServerCertificate),
                null);
            try
            {
                // server name must match name on the server certificate.
                sslStream.AuthenticateAsClient(serverName);
                Console.WriteLine("sslStream AuthenticateAsClient completed.");
            }
            catch (AuthenticationException e)
            {
                Console.WriteLine("Exception: {0}", e.Message);
                if (e.InnerException != null)
                {
                    Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                }
                Console.WriteLine("Authentication failed - closing the connection.");
                client.Close();
                return;
            }

            // Send initiation command to the server.
            // Encode to a byte array.
            byte[] messsage = Encoding.UTF8.GetBytes(initiation_command + "\n");
            sslStream.Write(messsage);
            sslStream.Flush();

            //read from server, print to console:
            StreamReader sr;
            if (useCompression)
            {
                sr = new StreamReader(new DeflateStream(sslStream, CompressionMode.Decompress));
            }
            else
            {
                sr = new StreamReader(sslStream);
            }
            int limit = 1000;
            while (limit > 0)
            {
                string line = sr.ReadLine();
                Console.WriteLine(" Received: " + line);
                parse(line);
                limit--;
            }

            // Close the client connection.
            sr.Close();
            client.Close();
            Console.WriteLine("Client closed.");
        }

        public static void parse(string mes)
        {
            //parse with JSON.NET
            FlightObject flight = JsonConvert.DeserializeObject(mes);
            Console.WriteLine(" --------------- Message ------------------ \n");
            Console.WriteLine(flight.toString());
            Console.WriteLine(" ------------------------------------------ \n");
        }

        public static int Main(string[] args)
        {

            // machineName is the host running the server application.
            String machineName = "firehose.flightaware.com";
            String serverCertificateName = machineName;

            //connect, read data
            SSLClient.RunClient(machineName, serverCertificateName);

            Console.WriteLine(" Hit Enter to end ...");
            Console.Read();
            return 0;
        }
    }
}

Visual Studio or SharpDeveloper offer IDE that make development and testing easier.

Alternatively, you can run commands (Win32):


        Compile:

                csc ProgramName.cs

        Run:

                ProgramName
    

What to expect


sslStream AuthenticateAsClient completed.
 Received:  {"type":"position","ident":"AAL363","air_ground":"A","alt":"37200","
lock":"1417488737","id":"AAL363-1417242628-airline-0282","gs":"374","heading":"
79","lat":"42.81940","lon":"-83.97197","reg":"N930NN","updateType":"A"}

 ------------------- Message ----------------------

 type       position
 ident      AAL363
 airground  A
 alt        37200
 clock      1417488737
 id         AAL363-1417242628-airline-0282
 gs         374
 heading    279
 lat        42.81940
 lon        -83.97197
 reg        N930NN
 squawk
 updateType A

 -------------------------------------------------

 Received:  {"type":"position","ident":"AWE798","air_ground":"A","alt":"37000","
lock":"1417488736","id":"AWE798-1417242974-airline-0052","gs":"545","heading":"
2","lat":"43.14862","lon":"-68.63178","reg":"N206UW","updateType":"A"}

 ------------------- Message ----------------------

 type       position
 ident      AWE798
 airground  A
 alt        37000
 clock      1417488736
 id         AWE798-1417242974-airline-0052
 gs         545
 heading    42
 lat        43.14862
 lon        -68.63178
 reg        N206UW
 squawk
 updateType A

 -------------------------------------------------

Python

Show example ...

Requirements
  • Python 3

You can download python from www.python.org. Please note that while older versions of Python 2.7.9 or higher may work with this example, we encourage the use of Python 3.

What to change

Substitute your actual username and API key in the variables at the top of the program.

Change/remove count on the number of messages received.

Conversely, there are several IDEs for Python such as PyCharm that may make development and testing easier.


#!/usr/bin/env python

import json, socket, ssl, sys, time


username = "XXXXXXXXXX"
apikey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
compression = 0
servername = "firehose.flightaware.com"



# function to parse JSON data:
def parse_json( str ):
   try:
       # parse all data into dictionary decoded:
       decoded = json.loads(str)
       clocknow = time.time()
       diff = clocknow - int(decoded['pitr'])
       print "diff = {0:.2f} s".format(diff)
   except (ValueError, KeyError, TypeError):
       print("JSON format error: ", sys.exc_info()[0])
       print(str)
       #print(traceback.format_exc())
   return;

# Create socket
sock = socket.socket(socket.AF_INET)
# Create a SSL context with the recommended security settings for client sockets, including automatic certificate verification
context = ssl.create_default_context()
# Alternatively, a customized context could be created
#context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
#context.verify_mode = ssl.CERT_REQUIRED
#context.check_hostname = True
# Load a set of default CA certificates from default locations
#context.load_default_certs()

ssl_sock = context.wrap_socket(sock, server_hostname = servername)
print("Connecting...")
ssl_sock.connect((servername, 1501))
print("Connection succeeded")

# build the initiation command:
initiation_command = "live username {} password {}".format(username, apikey)
if compression:
   initiation_command += " compression gzip"

# send initialization command to server:
initiation_command += "\n"
if sys.version_info[0] >= 3:
    ssl_sock.write(bytes(initiation_command, 'UTF-8'))
else:
    ssl_sock.write(initiation_command)

# return a file object associated with the socket
if compression:
   if sys.version_info[0] >= 3:
      from gzip import GzipFile
      file = gzip.GzipFile(fileobj = ssl_sock.makefile('rb'), mode = 'r')
   else:
      # compression mode on Python 2 requires GzipStream handler from:
      # https://fedorahosted.org/spacewalk/wiki/Projects/python-gzipstream
      from gzipstream import GzipStream
      file = GzipStream(ssl_sock.makefile('r'), 'r')
else:
   file = ssl_sock.makefile('r')

# use "while True" for no limit in messages received
count = 10
while (count > 0):
   try :
      # read line from file:
      if sys.version_info[0] >= 3 and compression:
         inline = file.readline().decode('utf-8')
      else:
         inline = file.readline()

      # print(inline)

      # parse the line
      parse_json(inline)
      count = count - 1
   except socket.error as e:
      print('Connection fail', e)
      print(traceback.format_exc())

# wait for user input to end
# input("\n Press Enter to exit...");
# close the SSLSocket, will also close the underlying socket
ssl_sock.close()

Run commands



        python file_name.py
	

What to expect



Connecting...
Connection succeeded
 
******* Flight Info *******
 
reg        N279UP   
squawk     7362     
ident      UPS4913  
gs         536      
clock      1419271754
lon        -96.06475
air_ground A        
hexid      A2C9BB   
heading    80       
updateType A        
lat        37.76723 
alt        35000    
type       position 
id         UPS4913-1419253999-70-0
 
******* Flight Info *******
 
reg        N739MA   
squawk     1754     
ident      BSK323   
gs         252      
clock      1419271753
lon        -92.22064
air_ground A        
hexid      A9ED8E   
heading    157      
updateType A        
lat        38.71405 
alt        4800     
type       position 
id         BSK323-1419245889-42-0
 
******* Flight Info *******
 
reg        GEZIM    
lon        4.25537  
ident      EZY8418  
gs         436      
clock      1419271753
atcident   EZY76JA  
air_ground A        
hexid      400C4F   
heading    336      
squawk     6776     
updateType A        
lat        47.00784 
alt        33300    
type       position 
id         EZY8418-1419057854-airline-0406:0


Perl

Show example ...

Requirements
  • Perl 5

You can download Perl from www.perl.org. You may need to also install the perl modules that are referenced, by using the cpan utility. Please note that Perl 6 is not compatible with this example.

What to change

Substitute your actual username and API key in the variables at the top of the program.

Change/remove count on the number of messages received.


#!/usr/local/bin/perl

use strict;
use IO::Socket::SSL;
use JSON::PP;
use IO::Uncompress::Inflate qw($InflateError);
use Data::Dumper;

my $username = 'XXXXXXXXXX';
my $apikey = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
my $compression = 0;


# Open the TLS socket connection to FlightAware.
my $sock = IO::Socket::SSL->new('firehose-test.flightaware.com:1501') or die $!;
print "Connected!\n";

# Send the initiation command to the uncompressed socket.
my $initcmd = "live version 7.0 user $username password $apikey events \"flightplan position\"";
if ($compression) {
    $initcmd .= " compression compress";
}
binmode $sock;
print $sock "$initcmd\n";

# Activate compression, if requested.
my $zsock;
if ($compression) {
    $zsock = new IO::Uncompress::Inflate $sock
	or die "IO::Uncompress::Inflate failed: $InflateError\n";
} else {
    $zsock = $sock;
}

# Main loop, reading lines of JSON from the server.
my $i = 1;
while (my $line = $zsock->getline()) {
    #print "LINE $i\n";
    #print "LINE $i: ", $line, "\n";

    my $data = eval { decode_json $line };
    die "Failed to decode JSON: $line" if !defined($data) || $@;

    print "LINE $i\n" . Dumper($data);
    
    last if ($i++ >= 10);
}
close $sock;

print "All done.\n";

Run commands



        perl file_name.pl

	

What to expect



Connected!
LINE 1
$VAR1 = {
          'fdt' => '1473423300',
          'type' => 'flightplan',
          'status' => 'S',
          'dest' => 'EDDB',
          'facility_name' => 'Airline',
          'ete' => '6600',
          'eta' => '1473429900',
          'aircrafttype' => 'A319',
          'ident' => 'EZY6237',
          'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9',
          'pitr' => '1473380220',
          'speed' => '363',
          'orig' => 'EGGD',
          'edt' => '1473423300',
          'id' => 'EZY6237-1473226541-airline-0394'
        };
LINE 2
$VAR1 = {
          'ete' => '3720',
          'reg' => 'N8696E',
          'eta' => '1473377100',
          'waypoints' => [
                           {
                             'lon' => '-87.75',
                             'lat' => '41.79'
                           },
                           {
                             'lon' => '-87.84',
                             'lat' => '41.79'
                           },
                           {
                             'lat' => '41.79',
                             'lon' => '-87.87'
                           },
                           {
                             'lat' => '39.48',
                             'lon' => '-94.59'
                           },
                           {
                             'lon' => '-94.71',
                             'lat' => '39.3'
                           }
                         ],
          'dest' => 'KMCI',
          'facility_name' => 'Airline',
          'speed' => '467',
          'orig' => 'KMDW',
          'route' => 'KMDW./.VORIN041016..QUANE..BQS.BQS4.KMCI/2326',
          'edt' => '1473373380',
          'ident' => 'SWA3002',
          'pitr' => '1473380220',
          'aircrafttype' => 'B738',
          'status' => 'Z',
          'type' => 'flightplan',
          'fdt' => '1473373200',
          'alt' => '2700',
          'id' => 'SWA3002-1473140159-airline-0252',
          'hexid' => 'ABF375',
          'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9'
        };
LINE 3
$VAR1 = {
          'edt' => '1473468300',
          'speed' => '391',
          'orig' => 'KPIT',
          'pitr' => '1473380220',
          'ident' => 'FFT1093',
          'eta' => '1473484200',
          'reg' => 'N216FR',
          'ete' => '15900',
          'dest' => 'KLAS',
          'facility_name' => 'Airline',
          'id' => 'FFT1093-1473226201-airline-0321',
          'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9',
          'aircrafttype' => 'A320',
          'fdt' => '1473468300',
          'type' => 'flightplan',
          'status' => 'S'
        };
LINE 4
$VAR1 = {
          'dest' => 'EGCC',
          'facility_name' => 'Airline',
          'type' => 'flightplan',
          'fdt' => '1473449100',
          'status' => 'S',
          'eta' => '1473460200',
          'aircrafttype' => 'B738',
          'ete' => '10500',
          'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9',
          'pitr' => '1473380220',
          'ident' => 'RYR8895',
          'id' => 'RYR8895-1473226211-airline-0419',
          'edt' => '1473449700',
          'speed' => '384',
          'orig' => 'LIBR'
        };
LINE 5
$VAR1 = {
          'ident' => 'JAI364',
          'lon' => '73.26817',
          'pitr' => '1473380220',
          'gs' => '461',
          'lat' => '19.72847',
          'facility_name' => 'FlightAware ADS-B',
          'reg' => 'VTJBL',
          'updateType' => 'A',
          'heading' => '344',
          'facility_hash' => 'b4a580edcf3c4ba4302ce4aa6e3b36af39b1259f',
          'air_ground' => 'A',
          'altChange' => 'C',
          'clock' => '1473380210',
          'hexid' => '800547',
          'id' => 'JAI364-1473225942-airline-0283',
          'type' => 'position',
          'squawk' => '0302',
          'alt' => '26900'
        };
LINE 6
$VAR1 = {
          'type' => 'flightplan',
          'fdt' => '1473394500',
          'status' => 'S',
          'dest' => 'RPLL',
          'facility_name' => 'Airline',
          'ete' => '2700',
          'aircrafttype' => 'A320',
          'eta' => '1473397800',
          'ident' => 'CEB326',
          'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9',
          'pitr' => '1473380220',
          'speed' => '165',
          'orig' => 'RPLP',
          'edt' => '1473395100',
          'id' => 'CEB326-1473221700-schedule-0000'
        };
LINE 7
$VAR1 = {
          'pitr' => '1473380220',
          'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9',
          'ident' => 'ICE440',
          'edt' => '1473408600',
          'id' => 'ICE440-1473235200-schedule-0000',
          'speed' => '346',
          'orig' => 'BIKF',
          'dest' => 'EGCC',
          'facility_name' => 'Airline',
          'status' => 'S',
          'type' => 'flightplan',
          'fdt' => '1473408000',
          'aircrafttype' => 'B752',
          'eta' => '1473416700',
          'ete' => '8100'
        };
LINE 8
$VAR1 = {
          'type' => 'flightplan',
          'fdt' => '1473451500',
          'status' => 'S',
          'facility_name' => 'Airline',
          'dest' => 'EGCC',
          'ete' => '8400',
          'eta' => '1473460500',
          'aircrafttype' => 'B738',
          'ident' => 'RYR7545',
          'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9',
          'pitr' => '1473380220',
          'speed' => '320',
          'orig' => 'LEBL',
          'id' => 'RYR7545-1473226211-airline-0350',
          'edt' => '1473452100'
        };
LINE 9
$VAR1 = {
          'reg' => 'N132EV',
          'eta' => '1473383940',
          'ete' => '3900',
          'dest' => 'KDTW',
          'facility_name' => 'Airline',
          'waypoints' => [
                           {
                             'lat' => '40',
                             'lon' => '-82.89'
                           },
                           {
                             'lon' => '-82.86',
                             'lat' => '40.05'
                           },
                           {
                             'lat' => '40.11',
                             'lon' => '-82.81'
                           },
                           {
                             'lat' => '42.1',
                             'lon' => '-83.23'
                           },
                           {
                             'lat' => '42.11',
                             'lon' => '-83.25'
                           },
                           {
                             'lat' => '42.17',
                             'lon' => '-83.31'
                           },
                           {
                             'lon' => '-83.35',
                             'lat' => '42.21'
                           }
                         ],
          'edt' => '1473380040',
          'orig' => 'KCMH',
          'speed' => '431',
          'route' => 'KCMH..GIVES..DJB.GEMNI4.KDTW/0032',
          'pitr' => '1473380220',
          'ident' => 'ASQ5180',
          'aircrafttype' => 'CRJ9',
          'alt' => '25000',
          'status' => 'F',
          'fdt' => '1473379020',
          'type' => 'flightplan',
          'id' => 'ASQ5180-1473139757-airline-0499',
          'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9'
        };
LINE 10
$VAR1 = {
          'ident' => 'RYR4051',
          'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9',
          'pitr' => '1473380220',
          'orig' => 'LPFR',
          'speed' => '379',
          'id' => 'RYR4051-1473226208-airline-0472',
          'edt' => '1473437700',
          'fdt' => '1473437100',
          'type' => 'flightplan',
          'status' => 'S',
          'facility_name' => 'Airline',
          'dest' => 'EGCC',
          'ete' => '9600',
          'aircrafttype' => 'B738',
          'eta' => '1473447300'
        };
All done.

PHP

Show example ...

Requirements
  • PHP 5

You can download PHP from www.php.net. You may need to also install the perl modules that are referenced.

On FreeBSD systems, you can use: pkg install php56 php56-openssl php56-zlib php56-json

What to change

Substitute your actual username and API key in the variables at the top of the program.

Change/remove count on the number of messages received.


<?


$username = 'XXXXXXXXXX';
$apikey = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$compression = 0;


// Open the TLS socket connection to FlightAware.
$fp = fsockopen("tls://firehose.flightaware.com", 1501, $errno, $errstr, 30);
if (!$fp) {
   echo "Error connecting ($errno): $errstr\n";
   exit(1);
}
echo "Connected!\n";

// Send the initiation command to the uncompressed socket.
$initcmd = "live version 7.0 user $username password $apikey events \"flightplan position\"";
if ($compression) {
    // compress, gzip, deflate
    $initcmd .= " compression deflate";
}
fwrite($fp, "$initcmd\n");

// Apply a decompression filter, if requested.
if ($compression && !stream_filter_append($fp, 'zlib.inflate', STREAM_FILTER_READ)) {
   echo "Error appending filter.\n";
   exit(1);
}

// Main loop, reading lines of JSON from the server.
$i = 1;
while (($buffer = fgets($fp)) !== false) {
    echo "LINE $i\n";
    
    $data = json_decode($buffer);
    if (json_last_error() !== JSON_ERROR_NONE) {
        echo "Error: invalid json.\n";
        echo $buffer;
        break;
    }
    print_r($data);

    if ($i++ >= 10) {
        break;
    }
}
fclose($fp);
echo "All done.\n";

?>

Run commands



        php file_name.php

	

Tcl

Show example ...

Requirements
  • Tcl 8.6

You can download Tcl from www.tcl.tk. You may need to also install the Tcl packagees that are referenced. The yajltcl package can be downloaded from github yajl-tcl.

On FreeBSD systems, you can use: pkg install tcl86 yajl-tcl

What to change

Substitute your actual username and API key in the variables at the top of the program.

Change/remove count on the number of messages received.


#!/usr/bin/env tclsh

package require tls
package require yajltcl
package require zlib

set username "XXXXXXXXXXXXXXXXX"
set apikey "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

set hostname "firehose.flightaware.com"
set compression 0



# Open the TLS socket connection to FlightAware.
set sock [tls::socket -tls1 1 $hostname 1501]
puts "Connected!"

# Send the initiation command to the server.
set initcmd "live version 7.0 user $username password $apikey events {flightplan position}"
if {$compression} {
	append initcmd " compression deflate"
}

puts $sock "$initcmd"
flush $sock

# Activate compression, if requested.
if {$compression} {
	zlib push inflate $sock
}

# Main loop, reading lines of JSON from the server.
set linecount 1
while {$linecount < 10000} {
	if {[catch {set getResult [gets $sock line]} catchResult] == 1} {
		puts "Failed to get line from socket: $catchResult"
		break
	} elseif {$getResult < 0} {
		puts "Reached end of socket."
		break
	}

	puts "Line #$linecount"
	array unset data
	if {[catch {
		array set data [::yajl::json2dict $line]
	} catchResult] == 1} {
		puts "Failed to parse message: $line"
		break
	}
	parray data
	puts "========"

	incr linecount
}
close $sock

puts ""

Run commands



        tclsh file_name.tcl

	

Login

Don't have an account? Register now (free) for customized features, flight alerts, and more!