I have the below code. When I launch this in Chrome, the map with the overlay displays fine and there is no error message in the console. However, there is no response when clicking on the map. I have downloaded L.TileLayer.BetterWMS.js.

My issue is nearly similar if not similar to the following: https://stackoverflow.com/questions/55813632/how-to-get-attribute-info-of-wms-layer-published-in-geoserver-in-a-popup-via-le

However when I tried suggested solution

var nexrad = L.tileLayer.betterWMS("https://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", {
    layers: 'nexrad-n0r',
    format: 'image/png',
    transparent: true,
    attribution: "Weather data © 2015 IEM Nexrad"

I get an error message that:

Uncaught TypeError: L.tileLayer.betterWMS is not a function at addLayersLeaflet.html:129

Any guidance to point me to where my problem is?

Here is the code that display with no GetFeatureInfo response:

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

    //July 2019 - The following MapQuest URL is no longer supported as HTTPS endpoint and has been replaced with the ESRI WorldImagery tile layer.

             var MapQuestOpen_Aerial = L.tileLayer('http://oatile{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg', {               /*
            var MapQuestOpen_Aerial = L.tileLayer('h', {
                 attribution: 'Tiles Courtesy of <a href="http://www.mapquest.com/">MapQuest</a> &mdash; Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency',                   attribution: 'Tiles Courtesy of <a href="http://www.mapquest.com/">MapQuest</a> &mdash; Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency',
                 subdomains: '1234'                  subdomains: '1234'
             });                 });

            var Esri_WorldImagery = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
        attribution: 'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'

          var nexrad = var nexrad = L.tileLayer.betterWms("https://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", {
            layers: 'nexrad-n0r',
            format: 'image/png',
            transparent: true,
            attribution: "Weather data &copy; 2015 IEM Nexrad"

          //create the map
          var map = L.map('map', {
            center: new L.LatLng(44, -91),
            zoom: 5,
            layers: [OSM, nexrad]
          //layer control
          var baseMaps = {
            "OpenStreetMap": OSM,
            "ESRI  World Imnagery": Esri_WorldImagery
          var overlayMaps = {
            "Radar": nexrad
          L.control.layers(baseMaps, overlayMaps).addTo(map);


L.TileLayer.BetterWMS js:

L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({

  onAdd: function (mapid) {
    // Triggered when the layer is added to a map.
    //   Register a click listener, then do all the upstream WMS things
    L.TileLayer.WMS.prototype.onAdd.call(this, mapid);
    map.on('click', this.getFeatureInfo, this);

  onRemove: function (mapid) {
    // Triggered when the layer is removed from a map.
    //   Unregister a click listener, then do all the upstream WMS things
    L.TileLayer.WMS.prototype.onRemove.call(this, mapid);
    map.off('click', this.getFeatureInfo, this);

  getFeatureInfo: function (evt) {
    // Make an AJAX request to the server and hope for the best
    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) {
    // Construct a GetFeatureInfo request URL given a point
    var point = this._map.latLngToContainerPoint(latlng, this._map.getZoom()),
        size = this._map.getSize(),

        params = {
          request: 'GetFeatureInfo',
          service: 'WMS',
          srs: 'EPSG:4326',
          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'] = point.x;
    params[params.version === '1.3.0' ? 'j' : 'y'] = point.y;

    return this._url + L.Util.getParamString(params, this._url, true);

  showGetFeatureInfo: function (err, latlng, content) {
    if (err) { console.log(err); return; } // do nothing if there's an error

    // Otherwise show the content in a popup, or something.
    L.popup({ maxWidth: 800})

L.tileLayer.betterWms = function (url, options) {
  return new L.TileLayer.BetterWMS(url, options);  
  • you seem to have way more code than would be required to show the issue
    – nmtoken
    Nov 19, 2019 at 13:48
  • I see the code I have put there is actually the same thing in the L.TileLayer.BetterWMS.js. I will edit the code. Nov 19, 2019 at 13:51
  • I currently get this error <?xml version='1.0' encoding="UTF-8" standalone="no" ?> <!DOCTYPE ServiceExceptionReport SYSTEM "schemas.opengis.net/wms/1.1.1/exception_1_1_1.dtd"> <ServiceExceptionReport version="1.1.1"> <ServiceException code="LayerNotDefined"> msWMSFeatureInfo(): WMS server error. Layer(s) specified in QUERY_LAYERS parameter is not offered by the service instance. </ServiceException> </ServiceExceptionReport> Nov 19, 2019 at 14:25

2 Answers 2


There might be nothing wrong with your code.

One issue if you are trying to query the nexrad-n0r layer (actually any layer) in the IEM WMS Service


is that (as can be seen in the GetCapabilities response above) none of the layers is queryable; so you will not be able to do a GetFeatureInfo request.

GetCapabilities response

  • 1
    You are absolutely right, the layer I was using to test was un queryable. My own WMS worked just perfectly. Nov 19, 2019 at 15:00

Got it working. Thank you @ nmtoken. This helped me https://gist.github.com/rclark/6908938 . Basically after cleaning the code I did this; var nexrad = L.tileLayer.betterWms and it is returning a WMS getfeatureinfo url.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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