How can I use a freely available public WMS server with Government Survey Permanent marks for a web application I am building?

This "GetCapabilities" xml: https://spatial-gis.information.qld.gov.au/arcgis/services/Location/SurveyControl/MapServer/WMSServer?request=GetCapabilities&service=WMS is where to start, but I am not exactly sure how to build a query string to return data to put into a MapBox or Leaflet type map.

I've tried a heap of combos, but regularly end up with errors like "Parameter 'layers' cannot be empty" on a request like this: https://spatial-gis.information.qld.gov.au/arcgis/services/Location/SurveyControl/MapServer/WmsServer?service=WMS&version=1.3.0&request=GetFeatureInfo&layers=destroyed&styles=&crs=EPSG:4326&bbox=136.891955,-29.734784,155.770310,-9.142266&width=1000&height=1000&info_format=application/geojson&format=application/geojson

Can anyone suggest an example of a working http request that returns some data? Once I see how this is done I should be right to go.

  • 1
    Welcome to GIS SE. As a new user, please take the Tour, which emphasizes the importance of asking One question per Question. If you have a bullet list of questions, it's likely that your Question will be closed until is can be edited to be sufficiently focused on one problem. We're a problem-solving site, so we need to know what you have tried and where you are stuck. How do I get started? Questions are likely bettered answered by a tutorial (which is unlikely to be found here).
    – Vince
    Commented Apr 25, 2023 at 4:55
  • See the ESRI documentation about the parameters of GetFeatureInfo enterprise.arcgis.com/en/server/10.3/publish-services/windows/…. At least you are missing query_layers, i, and j. I am not sure what you expect to get back, but GetFeatureInfo returns info about one feature that is closest to a single point on a map. That point is provided as pixel coordinates i and j and they present the pixels of the map that the corresponding GetMap request returns.
    – user30184
    Commented Apr 25, 2023 at 6:22
  • if you have epsg:4326 and version 1.3.0 then you must use crs in lat /long order. layers must be one or more comma separated from the list of layer names in the GetCapabilities. Format is the format of the map image, it must be from the GetMap list in the GetCapabilities
    – nmtoken
    Commented Apr 25, 2023 at 9:28

2 Answers 2


When in doubt you can read the standard which explains all the parameters that you need. However, since WMS is an open standard there are many clients out there that already know how to view WMS maps so perhaps you could consider using one of those rather than reinventing the wheel.


What is missing in your GetFeatureInfo request is query_layers parameter which is usually the same as layers parameter.

When trying to display Destroyed layer in Leaflet, it seemed to be empty. I had more success with CORS Sites layer.

Here is the code I used to display CORS Sites layer and get feature info on feature click:

L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({
  onAdd: function (map) {
    L.TileLayer.WMS.prototype.onAdd.call(this, map);
    map.on('click', this.getFeatureInfo, this);
  onRemove: function (map) {
    L.TileLayer.WMS.prototype.onRemove.call(this, map);
    map.off('click', this.getFeatureInfo, this);
  getFeatureInfo: function (evt) {
    var url = this.getFeatureInfoUrl(evt.latlng),
        showResults = L.Util.bind(this.showGetFeatureInfo, this);
      url: url,
      success: function (data, status, xhr) {
        var err = typeof data === 'string' ? null : data;
        showResults(err, evt.latlng, data);
      error: function (xhr, status, error) {
  getFeatureInfoUrl: function (latlng) {
    var point = this._map.latLngToContainerPoint(latlng, this._map.getZoom()),
        size = this._map.getSize(),
        params = {
          request: 'GetFeatureInfo',
          service: 'WMS',
          styles: this.wmsParams.styles,
          transparent: this.wmsParams.transparent,
          version: this.wmsParams.version,      
          format: this.wmsParams.format,
          bbox: this._map.getBounds().toBBoxString(),
          height: size.y,
          width: size.x,
          layers: this.wmsParams.layers,
          query_layers: this.wmsParams.layers,
          info_format: 'text/html',
    params[params.version === '1.3.0' ? 'i' : 'x'] = Math.round(point.x);
    params[params.version === '1.3.0' ? 'j' : 'y'] = Math.round(point.y);
    params[params.version === '1.3.0' ? 'crs' : 'srs'] = 'EPSG:4326';
    var url = this._url + L.Util.getParamString(params, this._url, true);
    if(typeof this.wmsParams.proxy !== "undefined") {
      console.log(this.wmsParams.proxy, this.wmsParams.proxyParamName);
      if(typeof this.wmsParams.proxyParamName == "undefined") {
        this.wmsParams.proxyParamName = 'url';
      _proxy = this.wmsParams.proxy + '?' + this.wmsParams.proxyParamName + '=';
      url = _proxy + encodeURIComponent(url);
    return url;
  showGetFeatureInfo: function (err, latlng, content) {
    if (err) { console.log(err); return; }
    content = '<div style="width: 100%; overflow-x: auto">' + content + '<div>';
    L.popup({maxWidth: 800, offset: L.point(0, - 10)})

L.tileLayer.betterWms = function (url, options) {
  return new L.TileLayer.BetterWMS(url, options);  

var map = L.map('map', {
  center: [-27, 152],
  zoom: 8

L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'

var url = 'https://spatial-gis.information.qld.gov.au:443/arcgis/services/Location/SurveyControl/MapServer/WMSServer';      
L.tileLayer.betterWms(url, {
  layers: 'CORS sites',
  transparent: true,
  format: 'image/gif',

This is the result with one feature info displayed upon click:

enter image description here

Code above uses WMS 1.1.1. When I tried WMS 1.3.0, GetFeatureInfo returned empty result. I didn't try to find the reason, since I copied code for L.TileLayer.BetterWMS from somewhere a long time ago.

  • The Destroyed layer is scale delimited. If you're not getting a result then the Map for which you are requesting point i/j may be out of the scale range
    – nmtoken
    Commented Apr 26, 2023 at 8:56
  • @nmtoken CORS Sites layer is also scale (zoom) limited, but whatever zoom tried for Destroyed layer, I couldn't get any visible results.
    – TomazicM
    Commented Apr 26, 2023 at 12:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.