
FlightCaster is a web application that offers information on flight delays. According to FlightCaster,
FlightCaster predicts flight delays. We use an advanced algorithm that scours data on every domestic flight for the past 10-years and matches it to real-time conditions.
That means you can use their site to guess if your flight (or that of your loved ones) is going to be on time. Here's a colorful sample. You can also check on airport weather and ground delays imposed by the FAA.
The site offers a web API you can use to consume flight data in your programs. That's why we're here, right?
As with other web APIs, you'll need a key to use their service. I have an API key, but in the examples below it has been removed. Get one!
Note: This article is very long so if you're not in the mood to scroll through hundreds of lines of VBA, you may want to read it at another time. If you happen to work for FlightCaster, read my Open Letter.
Like the other web API examples found here(Wordnik, Australian post codes, Delicious RSS feeds), these functions use similar techniques: call the web API, cache the response, load and parse it using the MSXML object model. Note that I didn't enumerate all the available methods. See the API documentation for all the data you can pull from the API.
When using the FlightCaster API, make sure you use the right flight identifier:
IATA issues 'controlled duplicates', so it is recommended that the ICAO identifier be used. Controlled duplicates are issued to regional airlines who do not operate in the same air space.
Note: This code uses the FlightCaster API but is not endorsed or certified by FlightCaster. Nor should the use of their logo imply endorsement. And for the record, that is true of any code found here. Any code that uses the fill-in-the-blank API is not endorsed or certified by fill-in-the-blank.
Also, don't forget to paste the helper functions into a standard module in the same project.
Get Airline Information
Pass in your API key and this function returns the following about each airline:
- callsign
- country
- IATA code
- ICAO code
- ID number
- airline name
Function GetAirlines(apiKey As String, Optional page As Long = 1, _
Optional resultsPerPage As Long = 30) As String()
' default for FlightCaster is 30 results
Dim xml As Object ' MSXML2.XMLHTTP
Dim tempFile As String
Dim tempString() As String
Dim result As String
Dim i As Long, j As Long
Dim numRows As Long
Dim numCols As Long
Dim xmlDoc As Object ' MSXML2.DOMDocument
Dim xmlDocRoot As Object ' MSXML2.IXMLDOMNode
Dim airlines As Object ' MSXML2.IXMLDOMNodeList
Dim airline As Object ' MSXML2.IXMLDOMNode
Dim airlineSubNodes As Object ' MSXML2.IXMLDOMNodeList
Dim airlineSubNode As Object ' MSXML2.IXMLDOMNode
Const TEMP_FILENAME As String = "GetAirlines"
Const XML_FILE_EXTENSION As String = ".xml"
' if XML file exists, don't requery website
tempFile = environ("temp") & "\" & TEMP_FILENAME & XML_FILE_EXTENSION
If Len(Dir(tempFile)) = 0 Then
Set xml = CreateObject("MSXML2.XMLHTTP.6.0")
With xml
.Open "GET", "http://api.flightcaster.com/airlines.xml?api_key=" & _
apiKey & "&api_version=0.1.1&page=" & page & "&per_page=" & resultsPerPage, False
.send
End With
result = xml.responseText
' save result as temp XML document
tempFile = CreateXMLFile(tempFile, result)
End If
' load XML file into new XML document
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
With xmlDoc
.async = False
.validateOnParse = False
.Load tempFile
End With
' check that the XML doc loaded
If LoadError(xmlDoc) Then
Exit Function
End If
' get root node
Set xmlDocRoot = GetRootNode(xmlDoc)
' get first level child nodes
Set airlines = GetChildNodes(xmlDocRoot)
' resize array
numRows = airlines.Length
numCols = airlines.item(0).childNodes.Length
ReDim tempString(1 To numRows, 1 To numCols)
' get second level child nodes
For i = 0 To numRows - 1
Set airline = airlines.item(i)
For j = 0 To numCols - 1
Set airlineSubNode = airline.childNodes.item(j)
tempString(i + 1, j + 1) = airlineSubNode.nodeTypedValue
Next j
Next i
GetAirlines = tempString
End FunctionTo check the number of entries, use
xmlDocRoot.attributes.getNamedItem("total-entries").nodeTypedValueand for the number of pages, check
xmlDocRoot.attributes.getNamedItem("total-pages").nodeTypedValueSample usage
This sample procedure returns the first five airlines in the FlightCaster database.
Sub TestFlightCaster()
Dim apiKey As String
Dim numberOfResults As Long
Dim results() As String
Dim i As Long
apiKey = "your API key here"
numberOfResults = 5
results = GetAirlines(apiKey, , numberOfResults)
For i = 1 To numberOfResults
Debug.Print results(i, 1)
Next i
End SubGet Information for specific airline
Using the ICAO ID you returned from the GetAirlines function, pass it (and your API key) to the GetAirline function to return information about a specific airline. The function returns the same information as GetAirlines, except for a single airline only.
- callsign
- country
- IATA code
- ICAO code
- ID number
- airline name
Function GetAirline(apiKey As String, ID As String) As String()
Dim xml As Object ' MSXML2.XMLHTTP
Dim tempFile As String
Dim uIdentifier As String
Dim tempString() As String
Dim result As String
Dim i As Long
Dim numCols As Long
Dim xmlDoc As Object ' MSXML2.DOMDocument
Dim xmlDocRoot As Object ' MSXML2.IXMLDOMNode
Dim airlines As Object ' MSXML2.IXMLDOMNodeList
Dim airline As Object ' MSXML2.IXMLDOMNode
Const TEMP_FILENAME As String = "GetAirline"
Const XML_FILE_EXTENSION As String = ".xml"
' if XML file exists, don't requery website
uIdentifier = UCase$(ID)
tempFile = environ("temp") & "\" & uIdentifier & XML_FILE_EXTENSION
If Len(Dir(tempFile)) = 0 Then
Set xml = CreateObject("MSXML2.XMLHTTP.6.0")
With xml
.Open "GET", "http://api.flightcaster.com/airlines/" & uIdentifier & _
".xml?api_key=" & apiKey & "&api_version=0.1.1", False
.send
End With
result = xml.responseText
' save result as temp XML document
tempFile = CreateXMLFile(tempFile, result)
End If
' load XML file into new XML document
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
With xmlDoc
.async = False
.validateOnParse = False
.Load tempFile
End With
' check that the XML doc loaded
If LoadError(xmlDoc) Then
Exit Function
End If
' get root node
Set xmlDocRoot = GetRootNode(xmlDoc)
' get first level child nodes
Set airlines = GetChildNodes(xmlDocRoot)
' resize array
numCols = airlines.Length
ReDim tempString(1 To numCols)
For i = 0 To numCols - 1
' get second level child nodes
Set airline = airlines.item(i)
tempString(i + 1) = airline.nodeTypedValue
Next i
GetAirline = tempString
End FunctionSample usage
This procedure returns the airline information for Chautauqua Airlines (ICAO ID: CHQ), which operates in the U.S.
Sub TestFlightCaster()
Dim apiKey As String
Dim identifier As String
Dim results() As String
Dim i As Long
apiKey = "your API key here"
identifier = "CHQ"
results = GetAirline(apiKey, identifier)
For i = 1 To UBound(results)
Debug.Print results(i)
Next i
End SubUsing this we can write a procedure that accepts any ICAO ID and returns the name of the airline:
Function GetAirlineName(ICAO As String) As String Dim apiKey As String Dim identifier As String Dim results() As String Dim i As Long apiKey = "your API key here" identifier = ICAO results = GetAirline(apiKey, identifier) GetAirlineName = results(UBound(results)) End Sub
Return flight information for a specific airline
The following function returns a wealth of information about available flights for a given airline. In this case I chose to return all available data points.
- ID
- Flightstats ID (for use with FlightStats)
- Number
- airline ICAO ID
- origin ICAO ID
- destination ICAO ID
- diverted ICAO ID (if applicable)
- published arrival time
- published departure time
- date created
- date updated
And what you were all waiting for: on time probability
- On Time
- 60 minutes late
- More than one hour late
In all, there are fourteen data points for each flight.
Function GetFlightsPerAirlineID(apiKey As String, ID As String, Optional page As Long = 1, _
Optional resultsPerPage As Long = 30, Optional forceRequery As Boolean = False) As String()
Dim xml As Object ' MSXML2.XMLHTTP
Dim tempFile As String
Dim tempString() As String
Dim result As String
Dim xmlDoc As Object ' MSXML2.DOMDocument
Dim xmlDocRoot As Object ' MSXML2.IXMLDOMNode
Dim flights As Object ' MSXML2.IXMLDOMNodeList
Dim subFlights As Object ' MSXML2.IXMLDOMNodeList
Dim flight As Object ' MSXML2.IXMLDOMNode
Dim i As Long, j As Long
Const TEMP_FILENAME As String = "GetFlightsPerAirlineID"
Const XML_FILE_EXTENSION As String = ".xml"
' if XML file exists or we force requery, don't requery website
tempFile = environ("temp") & "\" & TEMP_FILENAME & ID & XML_FILE_EXTENSION
If Len(Dir(tempFile)) = 0 Or forceRequery Then
Set xml = CreateObject("MSXML2.XMLHTTP.6.0")
With xml
.Open "GET", "http://api.flightcaster.com/airlines/" & ID & "/flights.xml?api_key=" & apiKey & "&api_version=0.1.1&page=" & page & "&per_page=" & resultsPerPage, False
.send
End With
result = xml.responseText
' save result as temp XML document
Call CreateXMLFile(tempFile, result)
End If
' load XML file into new XML document
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
With xmlDoc
.async = False
.validateOnParse = False
.Load tempFile
End With
' check that the XML doc loaded
If LoadError(xmlDoc) Then
Exit Function
End If
' get root node
Set xmlDocRoot = GetRootNode(xmlDoc)
' get first level child nodes
Set flights = GetChildNodes(xmlDocRoot)
' resize array
' each node has 14 data points to extract
ReDim tempString(1 To flights.Length, 1 To 14)
For i = 1 To flights.Length
Set flight = flights.item(i - 1)
' for the first 11 nodes, loop as usual
' for the last node, loop through it
For j = 1 To flight.childNodes.Length
Select Case j
Case Is < 12
tempString(i, j) = flight.childNodes(j - 1).nodeTypedValue
Case Else
Set subFlights = flights.item(j).childNodes
tempString(i, j) = subFlights.item(j - 1).childNodes(0).nodeTypedValue
tempString(i, j + 1) = subFlights.item(j - 1).childNodes(1).nodeTypedValue
tempString(i, j + 2) = subFlights.item(j - 1).childNodes(2).nodeTypedValue
End Select
Next j
Next i
GetFlightsPerAirlineID = tempString
End FunctionTo check the number of entries, use
xmlDocRoot.attributes.getNamedItem("total-entries").nodeTypedValueand for the number of pages, check
xmlDocRoot.attributes.getNamedItem("total-pages").nodeTypedValueSample usage
Let's again use Chautauqua Airlines (ICAO ID: CHQ) as an example.
Sub TestFlightCaster()
Dim apiKey As String
Dim results() As String
Dim i As Long, j As Long
apiKey = "your API key here"
results = GetFlightsPerAirlineID(apiKey, "CHQ")
For i = LBound(results) To UBound(results)
For j = LBound(results, 2) To UBound(results, 2)
Debug.Print results(i, j)
Next j
Next i
End SubReturn airport information
This function will return information about all available airports. Each airport has 12 data points:
- City
- Country
- Elevation
- FAA ID
- IATA ID
- ICAO ID
- ID (this is the FlightCaster ID)
- Latitude
- Longitude
- Airport Name
- State
- Time zone
Run this function first to find out what airports are listed, and the ICAO ID for each.
Function GetAirports(apiKey As String, Optional page As Long = 1, _
Optional resultsPerPage As Long = 30) As String()
Dim xml As Object ' MSXML2.XMLHTTP
Dim tempFile As String
Dim tempString() As String
Dim result As String
Dim numRows As Long
Dim numCols As Long
Dim i As Long, j As Long
Dim xmlDoc As Object ' MSXML2.DOMDocument
Dim xmlDocRoot As Object ' MSXML2.IXMLDOMNode
Dim airports As Object ' MSXML2.IXMLDOMNodeList
Dim airport As Object ' MSXML2.IXMLDOMNode
Dim airportSubNodes As Object ' MSXML2.IXMLDOMNodeList
Dim airportSubNode As Object ' MSXML2.IXMLDOMNode
Const TEMP_FILENAME As String = "GetAirports"
Const XML_FILE_EXTENSION As String = ".xml"
' if XML file exists, don't requery website
tempFile = environ("temp") & "\" & TEMP_FILENAME & XML_FILE_EXTENSION
If Len(Dir(tempFile)) = 0 Then
Set xml = CreateObject("MSXML2.XMLHTTP.6.0")
With xml
.Open "GET", "http://api.flightcaster.com/airports.xml?api_key=" & apiKey & "&api_version=0.1.1&page=" & page & "&per_page=" & resultsPerPage, False
.send
End With
result = xml.responseText
' save result as temp XML document
tempFile = CreateXMLFile(tempFile, result)
End If
' load XML file into new XML document
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
With xmlDoc
.async = False
.validateOnParse = False
.Load tempFile
End With
' check that the XML doc loaded
If LoadError(xmlDoc) Then
Exit Function
End If
' get root node
Set xmlDocRoot = GetRootNode(xmlDoc)
' get first level child nodes
Set airports = GetChildNodes(xmlDocRoot)
' resize array
numRows = airports.Length
numCols = airports.item(0).childNodes.Length
ReDim tempString(1 To numRows, 1 To numCols)
' get second level child nodes
For i = 0 To numRows - 1
Set airport = airports.item(i)
For j = 0 To numCols - 1
Set airportSubNode = airport.childNodes.item(j)
tempString(i + 1, j + 1) = airportSubNode.nodeTypedValue
Next j
Next i
GetAirports = tempString
End FunctionTo check the number of entries, use
xmlDocRoot.attributes.getNamedItem("total-entries").nodeTypedValueand for the number of pages, check
xmlDocRoot.attributes.getNamedItem("total-pages").nodeTypedValueSample usage
Sub TestFlightCaster()
Dim apiKey As String
Dim results() As String
Dim i As Long, j As Long
apiKey = "your API key here"
results = GetAirports(apiKey)
For i = LBound(results) To UBound(results)
For j = LBound(results, 2) To UBound(results, 2)
Debug.Print results(i, j)
Next j
Next i
End SubGet individual airport information
This function will return the same information as GetAirports, but only about a single airport. Pass in your API key and either the FlightCaster ID (the "ID" field from GetAirports), the IATA ID or the ICAO ID.
Function GetAirport(apiKey As String, ID As String) As String()
Dim xml As Object ' MSXML2.XMLHTTP
Dim tempFile As String
Dim tempString() As String
Dim result As String
Dim i As Long
Dim xmlDoc As Object ' MSXML2.DOMDocument
Dim xmlDocRoot As Object ' MSXML2.IXMLDOMNode
Dim airports As Object ' MSXML2.IXMLDOMNodeList
Const TEMP_FILENAME As String = "GetAirport"
Const XML_FILE_EXTENSION As String = ".xml"
' if XML file exists, don't requery website
tempFile = environ("temp") & "\" & TEMP_FILENAME & ID & XML_FILE_EXTENSION
If Len(Dir(tempFile)) = 0 Then
Set xml = CreateObject("MSXML2.XMLHTTP.6.0")
With xml
.Open "GET", "http://api.flightcaster.com/airports/" & ID & ".xml?api_key=" & apiKey & "&api_version=0.1.1", False
.send
End With
result = xml.responseText
' save result as temp XML document
tempFile = CreateXMLFile(tempFile, result)
End If
' load XML file into new XML document
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
With xmlDoc
.async = False
.validateOnParse = False
.Load tempFile
End With
' check that the XML doc loaded
If LoadError(xmlDoc) Then
Exit Function
End If
' get root node
Set xmlDocRoot = GetRootNode(xmlDoc)
' get first level child nodes
Set airports = GetChildNodes(xmlDocRoot)
' resize array
ReDim tempString(1 To airports.Length)
For i = 1 To airports.Length
tempString(i) = airports.item(i - 1).nodeTypedValue
Next i
GetAirport = tempString
End FunctionHere's a sample API response when using CHQ as an airport code:
<?xml version="1.0" encoding="utf-8" ?> <airport> <city>Charleston</city> <country>US</country> <elevation>95</elevation> <faa-id>CHQ</faa-id> <iata-id /> <icao-id>KCHQ</icao-id> <id>5882</id> <latitude>36.8421372</latitude> <longitude>-89.3596578</longitude> <name>Mississippi County Airport</name> <state>MO</state> <time-zone>America/Chicago</time-zone> </airport>
Sample usage
This example prints the airport information for airport IATA code CHQ (ICAO code KCHQ) to the Immediate Window.
Sub TestFlightCaster()
Dim apiKey As String
Dim results() As String
Dim i As Long
apiKey = "your API key here"
results = GetAirport(apiKey, "CHQ")
For i = 1 To UBound(results)
Debug.Print results(i)
Next i
End SubReturn flight information for a specific airline
This function returns the same information as GetFlightsPerAirlineID, including the on-time percentage. Just pass in the airport ID.
Function GetAirportArrivals(apiKey As String, ID As String, Optional page As Long = 1, _
Optional resultsPerPage As Long = 30, Optional forceRequery As Boolean = False) As String()
Dim xml As Object ' MSXML2.XMLHTTP
Dim tempFile As String
Dim tempString() As String
Dim result As String
Dim xmlDoc As Object ' MSXML2.DOMDocument
Dim xmlDocRoot As Object ' MSXML2.IXMLDOMNode
Dim flights As Object ' MSXML2.IXMLDOMNodeList
Dim subFlights As Object ' MSXML2.IXMLDOMNodeList
Dim flight As Object ' MSXML2.IXMLDOMNode
Dim i As Long, j As Long
Const TEMP_FILENAME As String = "GetAirportArrivals"
Const XML_FILE_EXTENSION As String = ".xml"
' if XML file exists or we force requery, don't requery website
tempFile = environ("temp") & "\" & TEMP_FILENAME & ID & XML_FILE_EXTENSION
If Len(Dir(tempFile)) = 0 Or forceRequery Then
Set xml = CreateObject("MSXML2.XMLHTTP.6.0")
With xml
.Open "GET", "http://api.flightcaster.com/airports/" & ID & "/arrivals.xml?api_key=" & apiKey & "&api_version=0.1.1&page=" & page & "&per_page=" & resultsPerPage, False
.send
End With
result = xml.responseText
' save result as temp XML document
Call CreateXMLFile(tempFile, result)
End If
' load XML file into new XML document
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
With xmlDoc
.async = False
.validateOnParse = False
.Load tempFile
End With
' check that the XML doc loaded
If LoadError(xmlDoc) Then
Exit Function
End If
' get root node
Set xmlDocRoot = GetRootNode(xmlDoc)
' make sure there are flights
If xmlDocRoot.Attributes.getNamedItem("total-entries").nodeTypedValue = 0 Then
MsgBox "No flights found", vbInformation
Exit Function
End If
' get first level child nodes
Set flights = GetChildNodes(xmlDocRoot)
' resize array
' each node has 14 data points to extract
ReDim tempString(1 To flights.Length, 1 To 14)
For i = 1 To flights.Length
Set flight = flights.item(i - 1)
' for the first 11 nodes, loop as usual
' for the last node, loop through it
For j = 1 To flight.childNodes.Length
Select Case j
Case Is < 12
tempString(i, j) = flight.childNodes(j - 1).nodeTypedValue
Case Else
Set subFlights = flights.item(j).childNodes
tempString(i, j) = subFlights.item(j - 1).childNodes(0).nodeTypedValue
tempString(i, j + 1) = subFlights.item(j - 1).childNodes(1).nodeTypedValue
tempString(i, j + 2) = subFlights.item(j - 1).childNodes(2).nodeTypedValue
End Select
Next j
Next i
GetAirportArrivals = tempString
End FunctionTo check the number of entries, use
xmlDocRoot.attributes.getNamedItem("total-entries").nodeTypedValueand for the number of pages, check
xmlDocRoot.attributes.getNamedItem("total-pages").nodeTypedValueSample usage
This sample procedure returns all the flights arriving at LaGuardia Airport.
Sub TestFlightCaster()
Dim apiKey As String
Dim results() As String
Dim i As Long, j As Long
apiKey = "your API key here"
results = GetAirportArrivals(apiKey, "LGA")
For i = LBound(results) To UBound(results)
For j = LBound(results, 2) To UBound(results, 2)
Debug.Print results(i, j)
Next j
Next i
End SubReturn departures for a specific airport
This function returns the same information as GetAirportArrivals and GetFlightsPerAirlineID. Pass in the airport ID and it returns the departures for that airport.
Function GetAirportDepartures(apiKey As String, ID As String, Optional page As Long = 1, _
Optional resultsPerPage As Long = 30, Optional forceRequery As Boolean = False) As String()
Dim xml As Object ' MSXML2.XMLHTTP
Dim tempFile As String
Dim tempString() As String
Dim result As String
Dim xmlDoc As Object ' MSXML2.DOMDocument
Dim xmlDocRoot As Object ' MSXML2.IXMLDOMNode
Dim flights As Object ' MSXML2.IXMLDOMNodeList
Dim subFlights As Object ' MSXML2.IXMLDOMNodeList
Dim flight As Object ' MSXML2.IXMLDOMNode
Dim i As Long, j As Long
Const TEMP_FILENAME As String = "GetAirportDepartures"
Const XML_FILE_EXTENSION As String = ".xml"
' if XML file exists or we force requery, don't requery website
tempFile = environ("temp") & "\" & TEMP_FILENAME & ID & XML_FILE_EXTENSION
If Len(Dir(tempFile)) = 0 Or forceRequery Then
Set xml = CreateObject("MSXML2.XMLHTTP.6.0")
With xml
.Open "GET", "http://api.flightcaster.com/airports/" & ID & "/departures.xml?api_key=" & apiKey & "&api_version=0.1.1&page=" & page & "&per_page=" & resultsPerPage, False
.send
End With
result = xml.responseText
' save result as temp XML document
Call CreateXMLFile(tempFile, result)
End If
' load XML file into new XML document
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
With xmlDoc
.async = False
.validateOnParse = False
.Load tempFile
End With
' check that the XML doc loaded
If LoadError(xmlDoc) Then
Exit Function
End If
' get root node
Set xmlDocRoot = GetRootNode(xmlDoc)
' make sure there are flights
If xmlDocRoot.Attributes.getNamedItem("total-entries").nodeTypedValue = 0 Then
MsgBox "No flights found", vbInformation
Exit Function
End If
' get first level child nodes
Set flights = GetChildNodes(xmlDocRoot)
' resize array
' each node has 14 data points to extract
ReDim tempString(1 To flights.Length, 1 To 14)
For i = 1 To flights.Length
Set flight = flights.item(i - 1)
' for the first 11 nodes, loop as usual
' for the last node, loop through it
For j = 1 To flight.childNodes.Length
Select Case j
Case Is < 12
tempString(i, j) = flight.childNodes(j - 1).nodeTypedValue
Case Else
Set subFlights = flights.item(j).childNodes
tempString(i, j) = subFlights.item(j - 1).childNodes(0).nodeTypedValue
tempString(i, j + 1) = subFlights.item(j - 1).childNodes(1).nodeTypedValue
tempString(i, j + 2) = subFlights.item(j - 1).childNodes(2).nodeTypedValue
End Select
Next j
Next i
GetAirportDepartures = tempString
End FunctionTo check the number of entries, use
xmlDocRoot.attributes.getNamedItem("total-entries").nodeTypedValueand for the number of pages, check
xmlDocRoot.attributes.getNamedItem("total-pages").nodeTypedValueSample usage
This sample procedure returns all the flights arriving at LaGuardia Airport.
Sub TestFlightCaster()
Dim apiKey As String
Dim results() As String
Dim i As Long, j As Long
apiKey = "your API key here"
results = GetAirportDepartures(apiKey, "LGA")
For i = LBound(results) To UBound(results)
For j = LBound(results, 2) To UBound(results, 2)
Debug.Print results(i, j)
Next j
Next i
End SubGet Flights From Specific Airports
Just like the other functions that return airline departures and flights (GetAirportDepartures and GetAirportArrivals), this function also returns flight information, except you can specify the origin and destination airports. Otherwise it returns the same information, including on-time percentage. To check the number of entries, use and for the number of pages, check This example prints the flight information for all flights leaving LaGuardia and landing at Dallas Fort Worth. This function allows you to further filter the list of available flights returned by GetFlightsToFromSpecificAirports. You can list flights by date. This will allow you to loop through a list of dates and call the function, returning the results to a listbox on a form. The date must be formatted as follows: yyyymmdd For example, 20100501 for May 1st, 2010. If you forget to format the date this way, the function will reformat it for you. To check the number of entries, use and for the number of pages, check This sample procedure further filters GetFlightsToFromSpecificAirports by limiting the results to May 20th, 2010. The following function will check for posted delays at a given airport. It returns Returns all available flights in the FlightCaster database. This function returns the same information as all the other functions that return flight information (GetFlightsPerAirlineID). Run this function to return the ID for each flight. To check the number of entries, use and for the number of pages, check This function returns the details for an individual flight. Run GetFlights first to get the flight ID. Otherwise it returns the same information. Delays happen all the time. This function will return the location and reason for delays at any airport in the FlightCaster database. To check the number of entries, use and for the number of pages, check You may also want to visit Ground Delay Program to see what the delay codes mean. Ground stops can occur during periods of bad weather (among other reasons). This function will return any ground stops currently in effect. If anyone from FlightCaster is reading, check your email: Your API documentation stinks. It's inaccurate in some places, and several links are redundant. On the Airport Resources page (http://docs.flightcaster.com/airports/), the link to airport arrivals is listed twice, but the first link is just a link to the existing page. In other words, it just reloads the current page. On the Airport Resources page (http://docs.flightcaster.com/airports/), there is a "FAA Programs" section. The first link says "/airports/:id/programs(.:format)" but when you go to the page (http://docs.flightcaster.com/airports/programs) it shows the link as "/airports/:id/delays(.:format)", i.e. a different description of the method. The next link is "/airports/:id/programs/ground_stops(.:format)" but that method returns a "Oops we couldn't find that" when I ran this query: http://api.flightcaster.com/airports/JFK/programs/ground_stops.xml?api_key= The ground delays method also doesn't return anything: http://api.flightcaster.com/airports/JFK/programs/ground_delays.xml?api_key= There's a redundant link on the Flight Resources page also — the first link under "Flights by Airport" is just a link to the existing page. On the General Delays page (http://docs.flightcaster.com/faa/general_delays/) there are two methods that start with "/faa/" but if you visit each page, the method doesn't start with "/faa/". But that is beside the point, because any way you call them, both methods (with "/faa/" and without "/faa/") return "Oops we couldn't find that". The Ground Delays and Ground Stops overview pages have almost the same problem — they both describe the methods as starting with "/faa/", but the individual method pages leave off the "/faa/" part. The difference is that if you leave off the "/faa/" they do work. Thanks for providing such a great service, but these issues with the documentation made it much harder and take much longer to write code than it should have. Update 6/24/2010: I finally heard from one of the FlightCaster developers, he let me know that the corrections I suggested have been made. –JPFunction GetFlightsToFromSpecificAirports(apiKey As String, fromAirport As String, toAirport As String, Optional page As Long = 1, _
Optional resultsPerPage As Long = 30, Optional forceRequery As Boolean = False) As String()
Dim xml As Object ' MSXML2.XMLHTTP
Dim tempFile As String
Dim tempString() As String
Dim result As String
Dim xmlDoc As Object ' MSXML2.DOMDocument
Dim xmlDocRoot As Object ' MSXML2.IXMLDOMNode
Dim flights As Object ' MSXML2.IXMLDOMNodeList
Dim subFlights As Object ' MSXML2.IXMLDOMNodeList
Dim flight As Object ' MSXML2.IXMLDOMNode
Dim i As Long, j As Long
Const TEMP_FILENAME As String = "GetFlightsToFromSpecificAirports"
Const XML_FILE_EXTENSION As String = ".xml"
' if XML file exists or we force requery, don't requery website
tempFile = environ("temp") & "\" & TEMP_FILENAME & fromAirport & toAirport & XML_FILE_EXTENSION
If Len(Dir(tempFile)) = 0 Or forceRequery Then
Set xml = CreateObject("MSXML2.XMLHTTP.6.0")
With xml
.Open "GET", "http://api.flightcaster.com/airports/" & fromAirport & "/departures/" & toAirport & ".xml?api_key=" & apiKey & "&api_version=0.1.1&page=" & page & "&per_page=" & resultsPerPage, False
.send
End With
result = xml.responseText
' save result as temp XML document
Call CreateXMLFile(tempFile, result)
End If
' load XML file into new XML document
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
With xmlDoc
.async = False
.validateOnParse = False
.Load tempFile
End With
' check that the XML doc loaded
If LoadError(xmlDoc) Then
Exit Function
End If
' get root node
Set xmlDocRoot = GetRootNode(xmlDoc)
' make sure there are flights
If xmlDocRoot.Attributes.getNamedItem("total-entries").nodeTypedValue = 0 Then
MsgBox "No flights found", vbInformation
Exit Function
End If
' get first level child nodes
Set flights = GetChildNodes(xmlDocRoot)
' resize array
' each node has 14 data points to extract
ReDim tempString(1 To flights.Length, 1 To 14)
For i = 1 To flights.Length
Set flight = flights.item(i - 1)
' for the first 11 nodes, loop as usual
' for the last node, loop through it
For j = 1 To flight.childNodes.Length
Select Case j
Case Is < 12
tempString(i, j) = flight.childNodes(j - 1).nodeTypedValue
Case Else
Set subFlights = flights.item(j).childNodes
tempString(i, j) = subFlights.item(j - 1).childNodes(0).nodeTypedValue
tempString(i, j + 1) = subFlights.item(j - 1).childNodes(1).nodeTypedValue
tempString(i, j + 2) = subFlights.item(j - 1).childNodes(2).nodeTypedValue
End Select
Next j
Next i
GetFlightsToFromSpecificAirports = tempString
End FunctionxmlDocRoot.attributes.getNamedItem("total-entries").nodeTypedValuexmlDocRoot.attributes.getNamedItem("total-pages").nodeTypedValueSample usage
Sub TestFlightCaster()
Dim apiKey As String
Dim results() As String
Dim i As Long, j As Long
apiKey = "your API key here"
results = GetFlightsToFromSpecificAirports(apiKey, "LGA", "DFW")
For i = LBound(results) To UBound(results)
For j = LBound(results, 2) To UBound(results, 2)
Debug.Print results(i, j)
Next j
Next i
End SubReturn flight information from specific airports by date
Function GetFlightsToFromSpecificAirportsOnDate(apiKey As String, fromAirport As String, _
toAirport As String, givenDate As Date, Optional page As Long = 1, _
Optional resultsPerPage As Long = 30, _
Optional forceRequery As Boolean = False) As String()
Dim xml As Object ' MSXML2.XMLHTTP
Dim tempFile As String
Dim tempString() As String
Dim result As String
Dim xmlDoc As Object ' MSXML2.DOMDocument
Dim xmlDocRoot As Object ' MSXML2.IXMLDOMNode
Dim flights As Object ' MSXML2.IXMLDOMNodeList
Dim subFlights As Object ' MSXML2.IXMLDOMNodeList
Dim flight As Object ' MSXML2.IXMLDOMNode
Dim i As Long, j As Long
Dim dateToCheck As String
Const TEMP_FILENAME As String = "GetFlightsToFromSpecificAirportsOnDate"
Const XML_FILE_EXTENSION As String = ".xml"
If Not IsDate(givenDate) Then
MsgBox "givenDate should be a Date type variable or a value like this: #mm/dd/yyyy#"
Exit Function
Else
dateToCheck = Format(givenDate, "yyyymmdd")
End If
' if XML file exists or we force requery, don't requery website
tempFile = environ("temp") & "\" & TEMP_FILENAME & fromAirport & toAirport & dateToCheck & XML_FILE_EXTENSION
If Len(Dir(tempFile)) = 0 Or forceRequery Then
Set xml = CreateObject("MSXML2.XMLHTTP.6.0")
With xml
.Open "GET", "http://api.flightcaster.com/airports/" & fromAirport & _
"/departures/" & toAirport & "/" & dateToCheck & ".xml?api_key=" & _
apiKey & "&api_version=0.1.1&page=" & page & "&per_page=" & resultsPerPage, False
.send
End With
result = xml.responseText
' save result as temp XML document
Call CreateXMLFile(tempFile, result)
End If
' load XML file into new XML document
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
With xmlDoc
.async = False
.validateOnParse = False
.Load tempFile
End With
' check that the XML doc loaded
If LoadError(xmlDoc) Then
Exit Function
End If
' get root node
Set xmlDocRoot = GetRootNode(xmlDoc)
' make sure there are flights
If xmlDocRoot.Attributes.getNamedItem("total-entries").nodeTypedValue = 0 Then
MsgBox "No flights found", vbInformation
Exit Function
End If
' get first level child nodes
Set flights = GetChildNodes(xmlDocRoot)
' resize array
' each node has 14 data points to extract
ReDim tempString(1 To flights.Length, 1 To 14)
For i = 1 To flights.Length
Set flight = flights.item(i - 1)
' for the first 11 nodes, loop as usual
' for the last node, loop through it
For j = 1 To flight.childNodes.Length
Select Case j
Case Is < 12
tempString(i, j) = flight.childNodes(j - 1).nodeTypedValue
Case Else
Set subFlights = flights.item(j).childNodes
tempString(i, j) = subFlights.item(j - 1).childNodes(0).nodeTypedValue
tempString(i, j + 1) = subFlights.item(j - 1).childNodes(1).nodeTypedValue
tempString(i, j + 2) = subFlights.item(j - 1).childNodes(2).nodeTypedValue
End Select
Next j
Next i
GetFlightsToFromSpecificAirportsOnDate = tempString
End FunctionxmlDocRoot.attributes.getNamedItem("total-entries").nodeTypedValuexmlDocRoot.attributes.getNamedItem("total-pages").nodeTypedValueSample usage
Sub TestFlightCaster()
Dim apiKey As String
Dim results() As String
Dim i As Long, j As Long
apiKey = "your API key here"
results = GetFlightsToFromSpecificAirportsOnDate(apiKey, "LGA", "DFW", #5/20/2010#)
For i = LBound(results) To UBound(results)
For j = LBound(results, 2) To UBound(results, 2)
Debug.Print results(i, j)
Next j
Next i
End SubCheck airport delays
Function GetAirportDelays(apiKey As String, airportID As String) As String()
Dim xml As Object ' MSXML2.XMLHTTP
Dim tempFile As String
Dim tempString() As String
Dim result As String
Dim xmlDoc As Object ' MSXML2.DOMDocument
Dim xmlDocRoot As Object ' MSXML2.IXMLDOMNode
Dim hash As Object ' MSXML2.IXMLDOMNodeList
Dim departureDelay As Object ' MSXML2.IXMLDOMNode
Dim i As Long
Const TEMP_FILENAME As String = "GetAirportDelays"
Const XML_FILE_EXTENSION As String = ".xml"
' if XML file exists, don't requery website
tempFile = environ("temp") & "\" & TEMP_FILENAME & airportID & XML_FILE_EXTENSION
If Len(Dir(tempFile)) = 0 Then
Set xml = CreateObject("MSXML2.XMLHTTP.6.0")
With xml
.Open "GET", "http://api.flightcaster.com/airports/" & airportID & "/delays.xml?api_key=" & apiKey & "&api_version=0.1.1", False
.send
End With
result = xml.responseText
' save result as temp XML document
tempFile = CreateXMLFile(tempFile, result)
End If
' load XML file into new XML document
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
With xmlDoc
.async = False
.validateOnParse = False
.Load tempFile
End With
' check that the XML doc loaded
If LoadError(xmlDoc) Then
Exit Function
End If
' get root node
Set xmlDocRoot = GetRootNode(xmlDoc)
' if there are no delays, root node will be empty
If (Len(xmlDocRoot.nodeTypedValue) > 0) Then
Set hash = GetChildNodes(xmlDocRoot)
Set departureDelay = hash.item(0)
' resize array
ReDim tempString(1 To departureDelay.childNodes.Length)
For i = 1 To departureDelay.childNodes.Length
tempString(i) = departureDelay.childNodes(i - 1).nodeTypedValue
Next i
End If
GetAirportDelays = tempString
End FunctionSample usage
Sub TestFlightCaster()
Dim apiKey As String
Dim results() As String
Dim i As Long, j As Long
apiKey = "your API key here"
results = GetAirportDelays(apiKey, "LGA")
For i = 1 To UBound(results)
Debug.Print results(i)
Next i
End SubGet flights
Function GetFlights(apiKey As String, Optional page As Long = 1, _
Optional resultsPerPage As Long = 30, _
Optional forceRequery As Boolean = False) As String()
Dim xml As Object ' MSXML2.XMLHTTP
Dim tempFile As String
Dim tempString() As String
Dim result As String
Dim xmlDoc As Object ' MSXML2.DOMDocument
Dim xmlDocRoot As Object ' MSXML2.IXMLDOMNode
Dim flights As Object ' MSXML2.IXMLDOMNodeList
Dim subFlights As Object ' MSXML2.IXMLDOMNodeList
Dim flight As Object ' MSXML2.IXMLDOMNode
Dim i As Long, j As Long
Const TEMP_FILENAME As String = "GetFlights"
Const XML_FILE_EXTENSION As String = ".xml"
' if XML file exists or we force requery, don't requery website
tempFile = environ("temp") & "\" & TEMP_FILENAME & XML_FILE_EXTENSION
If Len(Dir(tempFile)) = 0 Or forceRequery Then
Set xml = CreateObject("MSXML2.XMLHTTP.6.0")
With xml
.Open "GET", "http://api.flightcaster.com/flights.xml?api_key=" & _
apiKey & "&api_version=0.1.1&page=" & page & "&per_page=" & resultsPerPage, False
.send
End With
result = xml.responseText
' save result as temp XML document
Call CreateXMLFile(tempFile, result)
End If
' load XML file into new XML document
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
With xmlDoc
.async = False
.validateOnParse = False
.Load tempFile
End With
' check that the XML doc loaded
If LoadError(xmlDoc) Then
Exit Function
End If
' get root node
Set xmlDocRoot = GetRootNode(xmlDoc)
' make sure there are flights
If xmlDocRoot.Attributes.getNamedItem("total-entries").nodeTypedValue = 0 Then
MsgBox "No flights found", vbInformation
Exit Function
End If
' get first level child nodes
Set flights = GetChildNodes(xmlDocRoot)
' resize array
' each node has 14 data points to extract
ReDim tempString(1 To flights.Length, 1 To 14)
For i = 1 To flights.Length
Set flight = flights.item(i - 1)
' for the first 11 nodes, loop as usual
' for the last node, loop through it
For j = 1 To flight.childNodes.Length
Select Case j
Case Is < 12
tempString(i, j) = flight.childNodes(j - 1).nodeTypedValue
Case Else
Set subFlights = flights.item(j).childNodes
tempString(i, j) = subFlights.item(j - 1).childNodes(0).nodeTypedValue
tempString(i, j + 1) = subFlights.item(j - 1).childNodes(1).nodeTypedValue
tempString(i, j + 2) = subFlights.item(j - 1).childNodes(2).nodeTypedValue
End Select
Next j
Next i
GetFlights = tempString
End FunctionxmlDocRoot.attributes.getNamedItem("total-entries").nodeTypedValuexmlDocRoot.attributes.getNamedItem("total-pages").nodeTypedValueSample usage
Sub TestFlightCaster()
Dim apiKey As String
Dim results() As String
Dim i As Long, j As Long
apiKey = "your API key here"
results = GetFlights(apiKey)
For i = LBound(results) To UBound(results)
For j = LBound(results, 2) To UBound(results, 2)
Debug.Print results(i, j)
Next j
Next i
End SubGet specific flight
Function GetFlight(apiKey As String, flightID As String, _
Optional forceRequery As Boolean = False) As String()
Dim xml As Object ' MSXML2.XMLHTTP
Dim tempFile As String
Dim tempString() As String
Dim result As String
Dim xmlDoc As Object ' MSXML2.DOMDocument
Dim xmlDocRoot As Object ' MSXML2.IXMLDOMNode
Dim flights As Object ' MSXML2.IXMLDOMNodeList
Dim subFlights As Object ' MSXML2.IXMLDOMNodeList
Dim flight As Object ' MSXML2.IXMLDOMNode
Dim i As Long, j As Long
Const TEMP_FILENAME As String = "GetFlight"
Const XML_FILE_EXTENSION As String = ".xml"
' if XML file exists or we force requery, don't requery website
tempFile = environ("temp") & "\" & TEMP_FILENAME & flightID & XML_FILE_EXTENSION
If Len(Dir(tempFile)) = 0 Or forceRequery Then
Set xml = CreateObject("MSXML2.XMLHTTP.6.0")
With xml
.Open "GET", "http://api.flightcaster.com/flights/" & flightID & ".xml?api_key=" & _
apiKey & "&api_version=0.1.1", False
.send
End With
result = xml.responseText
' save result as temp XML document
Call CreateXMLFile(tempFile, result)
End If
' load XML file into new XML document
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
With xmlDoc
.async = False
.validateOnParse = False
.Load tempFile
End With
' check that the XML doc loaded
If LoadError(xmlDoc) Then
Exit Function
End If
' get root node
Set xmlDocRoot = GetRootNode(xmlDoc)
' get first level child nodes
Set flights = GetChildNodes(xmlDocRoot)
' resize array
' there are 14 data points for each flight
ReDim tempString(1 To 14)
' array has 14 elements, but we only loop 12 times because there are only 12 nodes
For i = 1 To flights.Length
' for the first 11 nodes, loop as usual
' for the last node, loop through it
Select Case i
Case Is < 12
tempString(i) = flights.item(i - 1).nodeTypedValue
Case Else
Set subFlights = flights.item(i - 1).childNodes
tempString(i) = subFlights.item(0).nodeTypedValue
tempString(i + 1) = subFlights.item(1).nodeTypedValue
tempString(i + 2) = subFlights.item(2).nodeTypedValue
End Select
Next i
GetFlight = tempString
End FunctionSample usage
Sub TestFlightCaster()
Dim apiKey As String
Dim results() As String
Dim i As Long, j As Long
apiKey = "your API key here"
results = GetFlight(apiKey, "191219033")
For i = 1 To UBound(results)
Debug.Print results(i)
Next i
End SubReturn ground delays
Function GetGroundDelays(apiKey As String, Optional page As Long = 1, _
Optional resultsPerPage As Long = 30, _
Optional forceRequery As Boolean = False) As String()
Dim xml As Object ' MSXML2.XMLHTTP
Dim tempFile As String
Dim tempString() As String
Dim result As String
Dim xmlDoc As Object ' MSXML2.DOMDocument
Dim xmlDocRoot As Object ' MSXML2.IXMLDOMNode
Dim delays As Object ' MSXML2.IXMLDOMNodeList
Dim delay As Object ' MSXML2.IXMLDOMNode
Dim i As Long, j As Long
Const TEMP_FILENAME As String = "GetGroundDelays"
Const XML_FILE_EXTENSION As String = ".xml"
' if XML file exists or we force requery, don't requery website
tempFile = environ("temp") & "\" & TEMP_FILENAME & XML_FILE_EXTENSION
If Len(Dir(tempFile)) = 0 Or forceRequery Then
Set xml = CreateObject("MSXML2.XMLHTTP.6.0")
With xml
.Open "GET", "http://api.flightcaster.com/ground_delays.xml?api_key=" & _
apiKey & "&api_version=0.1.1&page=" & page & "&per_page=" & resultsPerPage, False
.send
End With
result = xml.responseText
' save result as temp XML document
Call CreateXMLFile(tempFile, result)
End If
' load XML file into new XML document
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
With xmlDoc
.async = False
.validateOnParse = False
.Load tempFile
End With
' check that the XML doc loaded
If LoadError(xmlDoc) Then
Exit Function
End If
' get root node
Set xmlDocRoot = GetRootNode(xmlDoc)
' make sure there are delays
If xmlDocRoot.Attributes.getNamedItem("total-entries").nodeTypedValue = 0 Then
MsgBox "No delays found", vbInformation
Exit Function
End If
' get first level child nodes
Set delays = GetChildNodes(xmlDocRoot)
' resize array
' each delay has five data points
ReDim tempString(1 To delays.Length, 1 To 5)
For i = 1 To delays.Length
Set delay = delays.item(i - 1)
For j = 1 To delay.childNodes.Length
tempString(i, j) = delay.childNodes(j - 1).nodeTypedValue
Next j
Next i
GetGroundDelays = tempString
End FunctionxmlDocRoot.attributes.getNamedItem("total-entries").nodeTypedValuexmlDocRoot.attributes.getNamedItem("total-pages").nodeTypedValueSample usage
Sub TestFlightCaster()
Dim apiKey As String
Dim results() As String
Dim i As Long, j As Long
apiKey = "your API key here"
results = GetGroundDelays(apiKey)
For i = LBound(results) To UBound(results)
For j = LBound(results, 2) To UBound(results, 2)
Debug.Print results(i, j)
Next j
Next i
End SubGround stops information
Function GetGroundStops(apiKey As String, Optional page As Long = 1, _
Optional resultsPerPage As Long = 30, _
Optional forceRequery As Boolean = False) As String()
Dim xml As Object ' MSXML2.XMLHTTP
Dim tempFile As String
Dim tempString() As String
Dim result As String
Dim xmlDoc As Object ' MSXML2.DOMDocument
Dim xmlDocRoot As Object ' MSXML2.IXMLDOMNode
Dim groundStops As Object ' MSXML2.IXMLDOMNodeList
Dim groundStop As Object ' MSXML2.IXMLDOMNode
Dim i As Long, j As Long
Const TEMP_FILENAME As String = "GetGroundStops"
Const XML_FILE_EXTENSION As String = ".xml"
' if XML file exists or we force requery, don't requery website
tempFile = environ("temp") & "\" & TEMP_FILENAME & XML_FILE_EXTENSION
If Len(Dir(tempFile)) = 0 Or forceRequery Then
Set xml = CreateObject("MSXML2.XMLHTTP.6.0")
With xml
.Open "GET", "http://api.flightcaster.com/ground_stops.xml?api_key=" & _
apiKey & "&api_version=0.1.1&page=" & page & "&per_page=" & resultsPerPage, False
.send
End With
result = xml.responseText
' save result as temp XML document
Call CreateXMLFile(tempFile, result)
End If
' load XML file into new XML document
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
With xmlDoc
.async = False
.validateOnParse = False
.Load tempFile
End With
' check that the XML doc loaded
If LoadError(xmlDoc) Then
Exit Function
End If
' get root node
Set xmlDocRoot = GetRootNode(xmlDoc)
' make sure there are delays
If xmlDocRoot.Attributes.getNamedItem("total-entries").nodeTypedValue = 0 Then
MsgBox "No stops found", vbInformation
Exit Function
End If
' get first level child nodes
Set groundStops = GetChildNodes(xmlDocRoot)
' resize array
' each stop has four data points
ReDim tempString(1 To groundStops.Length, 1 To 4)
For i = 1 To groundStops.Length
Set groundStop = groundStops.item(i - 1)
For j = 1 To groundStop.childNodes.Length
tempString(i, j) = groundStop.childNodes(j - 1).nodeTypedValue
Next j
Next i
GetGroundStops = tempString
End FunctionSample usage
Sub TestFlightCaster()
Dim apiKey As String
Dim results() As String
Dim i As Long, j As Long
apiKey = "your API key here"
results = GetGroundStops(apiKey)
For i = LBound(results) To UBound(results)
For j = LBound(results, 2) To UBound(results, 2)
Debug.Print results(i, j)
Next j
Next i
End SubAn Open Letter to FlightCaster
Related Articles:
Follow Me