I have recently been getting "HTTPError: HTTP Error 404: Not Found" errors when trying to use Cartopy. Even when I comment out the add features lines I am still getting this issue, so maybe it is caused by some of the other packages. I have clicked on the link and you do get the 404 message, however I am not sure where in my code I am still getting this issue if I comment out the add coastlines.
OS: CentOS 7
Some of the main packages in the environment:
Cartopy: 0.17.0 py36h0aa2c8f_1004 conda-forge
Python: 3.6.7 h381d211_1004 conda-forge
Satpy: 0.13.0 pyh326bf55_0 conda-forge
arm_pyart : 1.9.2 py36_0 conda-forge
metpy : 0.10.0 py36_1001 conda-forge
Conda info:
active environment : sats
active env location : /export/home/mbrewer/anaconda3/envs/sats
shell level : 2
user config file : /export/home/mbrewer/.condarc
populated config files : /export/home/mbrewer/.condarc
conda version : 4.6.11
conda-build version : 3.17.6
python version : 3.7.1.final.0
base environment : /export/home/mbrewer/anaconda3 (writable)
channel URLs : https://conda.anaconda.org/conda-forge/linux-64
https://conda.anaconda.org/conda-forge/noarch
https://repo.anaconda.com/pkgs/main/linux-64
https://repo.anaconda.com/pkgs/main/noarch
https://repo.anaconda.com/pkgs/free/linux-64
https://repo.anaconda.com/pkgs/free/noarch
https://repo.anaconda.com/pkgs/r/linux-64
https://repo.anaconda.com/pkgs/r/noarch
package cache : /export/home/mbrewer/anaconda3/pkgs
/export/home/mbrewer/.conda/pkgs
envs directories : /export/home/mbrewer/anaconda3/envs
/export/home/mbrewer/.conda/envs
platform : linux-64
user-agent : conda/4.6.11 requests/2.21.0 CPython/3.7.1 Linux/3.10.0-957.5.1.el7.x86_64 centos/7.6.1810 glibc/2.17
UID:GID : 789585339:1341200513
netrc file : None
offline mode : False
from satpy import Scene
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from metpy.plots import USCOUNTIES
from satpy import find_files_and_readers
from glob import glob
import matplotlib.pyplot as plt
import numpy as np
from satpy.writers import cf_writer
from satpy.writers import get_enhanced_image
from metpy.plots import USCOUNTIES # Make sure metpy is updated to latest version.
import xarray as xr
from pathlib import Path
import pyart
el = Path("/export/home/mbrewer/Documents/GMTED2010_15n030_0125deg.nc")
rad = Path("/export/home/mbrewer/Documents/radar_files/KBBX20181108_213133_V06")
radar = pyart.io.read_nexrad_archive(rad)
#gf = pyart.filters.GateFilter(radar)
#gf.exclude_transition()
#gf.exclude_above('reflectivity', 100) #Mask out dBZ above 100
#gf.exclude_below('reflectivity', 5) #Mask out dBZ below 5
#despec = pyart.correct.despeckle_field(radar, 'reflectivity',gatefilter = gf, size = 20) #The despeckling mask routine that takes out small noisey reflectivity bits not near the main plume
elev = xr.open_dataset(el)
scn = Scene(
filenames=glob("npp/*"),
reader='viirs_l1b')
scn.load(['true_color', 'I02'])
new_scn = scn.resample('northamerica')
var = get_enhanced_image(new_scn['true_color']).data
var = var.transpose('y', 'x', 'bands')
st = str(scn.attrs['sensor'])[2:-2]
fig = plt.figure(figsize=(20, 10), dpi=200)
crs = new_scn['true_color'].attrs['area'].to_cartopy_crs()
ax = fig.add_subplot(1, 1, 1, projection=crs)
ax.imshow(var.data, extent=(var.x[0], var.x[-1], var.y[-1], var.y[0]), origin='upper')
ax.add_feature(cfeature.COASTLINE.with_scale('10m'), edgecolor='orange')
ax.add_feature(cfeature.STATES.with_scale('10m'), edgecolor='orange')
ax.add_feature(USCOUNTIES.with_scale('500k'), edgecolor='orange', alpha = .75)
ax.set_extent([-122.5, -120.5, 39., 40.5], crs=ccrs.PlateCarree())
display = pyart.graph.RadarMapDisplayCartopy(radar)
display.plot_ppi_map('reflectivity', 0, resolution = 'h', #The "0" is the lowest PPI scan, increasing this number increases the scanning elevation
vmin=-10, vmax=64, colorbar_flag = False, fig = fig, ax=ax,alpha = .08, projection = crs)#, gatefilter = gf)
display.plot_colorbar(ax =ax)
plt.title('Satellite: %s'%(st), loc='left', fontweight='bold', fontsize = 18)
plt.title('Radar: KBBX', loc='center', fontsize = 15)
plt.title('Satellite Time:\n%s\nRadar Time:\n%s' % (scn.attrs['start_time'].strftime("%Y-%m-%d %H:%M:%S"),radar.time['units'][14:24] + ' ' + radar.time['units'][25:]), loc='right', fontsize = 12)
export/home/mbrewer/anaconda3/envs/sats/lib/python3.6/site-packages/dask/core.py:119: RuntimeWarning: invalid value encountered in log
return func(*args2)
/export/home/mbrewer/anaconda3/envs/sats/lib/python3.6/site-packages/dask/core.py:119: RuntimeWarning: invalid value encountered in less
return func(*args2)
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Text(1.0, 1.0, 'Satellite Time:\n2018-11-08 21:30:00\nRadar Time:\n2018-11-08 21:31:33Z')
/export/home/mbrewer/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/io/__init__.py:260: DownloadWarning: Downloading: http://naciscdn.org/naturalearth/h/physical/ne_h_coastline.zip
warnings.warn('Downloading: {}'.format(url), DownloadWarning)
Error in callback <function install_repl_displayhook.<locals>.post_execute at 0x7fac46e28488> (for post_execute):
---------------------------------------------------------------------------
HTTPError Traceback (most recent call last)
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/pyplot.py in post_execute()
107 def post_execute():
108 if matplotlib.is_interactive():
--> 109 draw_all()
110
111 # IPython >= 2
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/_pylab_helpers.py in draw_all(cls, force)
130 for f_mgr in cls.get_all_fig_managers():
131 if force or f_mgr.canvas.figure.stale:
--> 132 f_mgr.canvas.draw_idle()
133
134 atexit.register(Gcf.destroy_all)
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/backend_bases.py in draw_idle(self, *args, **kwargs)
1897 if not self._is_idle_drawing:
1898 with self._idle_draw_cntx():
-> 1899 self.draw(*args, **kwargs)
1900
1901 def draw_cursor(self, event):
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/backends/backend_agg.py in draw(self)
400 toolbar = self.toolbar
401 try:
--> 402 self.figure.draw(self.renderer)
403 # A GUI class may be need to update a window using this draw, so
404 # don't forget to call the superclass.
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
48 renderer.start_filter()
49
---> 50 return draw(artist, renderer, *args, **kwargs)
51 finally:
52 if artist.get_agg_filter() is not None:
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/figure.py in draw(self, renderer)
1647
1648 mimage._draw_list_compositing_images(
-> 1649 renderer, self, artists, self.suppressComposite)
1650
1651 renderer.close_group('figure')
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
136 if not_composite or not has_images:
137 for a in artists:
--> 138 a.draw(renderer)
139 else:
140 # Composite any adjacent images together
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
48 renderer.start_filter()
49
---> 50 return draw(artist, renderer, *args, **kwargs)
51 finally:
52 if artist.get_agg_filter() is not None:
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/mpl/geoaxes.py in draw(self, renderer, inframe)
386
387 return matplotlib.axes.Axes.draw(self, renderer=renderer,
--> 388 inframe=inframe)
389
390 def __str__(self):
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
48 renderer.start_filter()
49
---> 50 return draw(artist, renderer, *args, **kwargs)
51 finally:
52 if artist.get_agg_filter() is not None:
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe)
2626 renderer.stop_rasterizing()
2627
-> 2628 mimage._draw_list_compositing_images(renderer, self, artists)
2629
2630 renderer.close_group('axes')
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
136 if not_composite or not has_images:
137 for a in artists:
--> 138 a.draw(renderer)
139 else:
140 # Composite any adjacent images together
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
48 renderer.start_filter()
49
---> 50 return draw(artist, renderer, *args, **kwargs)
51 finally:
52 if artist.get_agg_filter() is not None:
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/mpl/feature_artist.py in draw(self, renderer, *args, **kwargs)
162 except ValueError:
163 warnings.warn('Unable to determine extent. Defaulting to global.')
--> 164 geoms = self._feature.intersecting_geometries(extent)
165
166 # Combine all the keyword args in priority order.
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/feature/__init__.py in intersecting_geometries(self, extent)
301 """
302 self.scaler.scale_from_extent(extent)
--> 303 return super(NaturalEarthFeature, self).intersecting_geometries(extent)
304
305 def with_scale(self, new_scale):
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/feature/__init__.py in intersecting_geometries(self, extent)
118 extent_geom = sgeom.box(extent[0], extent[2],
119 extent[1], extent[3])
--> 120 return (geom for geom in self.geometries() if
121 geom is not None and extent_geom.intersects(geom))
122 else:
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/feature/__init__.py in geometries(self)
285 path = shapereader.natural_earth(resolution=self.scale,
286 category=self.category,
--> 287 name=self.name)
288 geometries = tuple(shapereader.Reader(path).geometries())
289 _NATURAL_EARTH_GEOM_CACHE[key] = geometries
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/io/shapereader.py in natural_earth(resolution, category, name)
357 format_dict = {'config': config, 'category': category,
358 'name': name, 'resolution': resolution}
--> 359 return ne_downloader.path(format_dict)
360
361
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/io/__init__.py in path(self, format_dict)
220 else:
221 # we need to download the file
--> 222 result_path = self.acquire_resource(target_path, format_dict)
223
224 return result_path
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/io/shapereader.py in acquire_resource(self, target_path, format_dict)
412 url = self.url(format_dict)
413
--> 414 shapefile_online = self._urlopen(url)
415
416 zfh = ZipFile(six.BytesIO(shapefile_online.read()), 'r')
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/io/__init__.py in _urlopen(self, url)
259 """
260 warnings.warn('Downloading: {}'.format(url), DownloadWarning)
--> 261 return urlopen(url)
262
263 @staticmethod
~/anaconda3/envs/sats/lib/python3.6/urllib/request.py in urlopen(url, data, timeout, cafile, capath, cadefault, context)
221 else:
222 opener = _opener
--> 223 return opener.open(url, data, timeout)
224
225 def install_opener(opener):
~/anaconda3/envs/sats/lib/python3.6/urllib/request.py in open(self, fullurl, data, timeout)
530 for processor in self.process_response.get(protocol, []):
531 meth = getattr(processor, meth_name)
--> 532 response = meth(req, response)
533
534 return response
~/anaconda3/envs/sats/lib/python3.6/urllib/request.py in http_response(self, request, response)
640 if not (200 <= code < 300):
641 response = self.parent.error(
--> 642 'http', request, response, code, msg, hdrs)
643
644 return response
~/anaconda3/envs/sats/lib/python3.6/urllib/request.py in error(self, proto, *args)
568 if http_err:
569 args = (dict, 'default', 'http_error_default') + orig_args
--> 570 return self._call_chain(*args)
571
572 # XXX probably also want an abstract factory that knows when it makes
~/anaconda3/envs/sats/lib/python3.6/urllib/request.py in _call_chain(self, chain, kind, meth_name, *args)
502 for handler in handlers:
503 func = getattr(handler, meth_name)
--> 504 result = func(*args)
505 if result is not None:
506 return result
~/anaconda3/envs/sats/lib/python3.6/urllib/request.py in http_error_default(self, req, fp, code, msg, hdrs)
648 class HTTPDefaultErrorHandler(BaseHandler):
649 def http_error_default(self, req, fp, code, msg, hdrs):
--> 650 raise HTTPError(req.full_url, code, msg, hdrs, fp)
651
652 class HTTPRedirectHandler(BaseHandler):
HTTPError: HTTP Error 404: Not Found
---------------------------------------------------------------------------
HTTPError Traceback (most recent call last)
~/anaconda3/envs/sats/lib/python3.6/site-packages/IPython/core/formatters.py in __call__(self, obj)
339 pass
340 else:
--> 341 return printer(obj)
342 # Finally look for special method names
343 method = get_real_method(obj, self.print_method)
~/anaconda3/envs/sats/lib/python3.6/site-packages/IPython/core/pylabtools.py in <lambda>(fig)
242
243 if 'png' in formats:
--> 244 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
245 if 'retina' in formats or 'png2x' in formats:
246 png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))
~/anaconda3/envs/sats/lib/python3.6/site-packages/IPython/core/pylabtools.py in print_figure(fig, fmt, bbox_inches, **kwargs)
126
127 bytes_io = BytesIO()
--> 128 fig.canvas.print_figure(bytes_io, **kw)
129 data = bytes_io.getvalue()
130 if fmt == 'svg':
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, **kwargs)
2047 orientation=orientation,
2048 dryrun=True,
-> 2049 **kwargs)
2050 renderer = self.figure._cachedRenderer
2051 bbox_artists = kwargs.pop("bbox_extra_artists", None)
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/backends/backend_agg.py in print_png(self, filename_or_obj, *args, **kwargs)
508
509 """
--> 510 FigureCanvasAgg.draw(self)
511 renderer = self.get_renderer()
512
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/backends/backend_agg.py in draw(self)
400 toolbar = self.toolbar
401 try:
--> 402 self.figure.draw(self.renderer)
403 # A GUI class may be need to update a window using this draw, so
404 # don't forget to call the superclass.
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
48 renderer.start_filter()
49
---> 50 return draw(artist, renderer, *args, **kwargs)
51 finally:
52 if artist.get_agg_filter() is not None:
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/figure.py in draw(self, renderer)
1647
1648 mimage._draw_list_compositing_images(
-> 1649 renderer, self, artists, self.suppressComposite)
1650
1651 renderer.close_group('figure')
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
136 if not_composite or not has_images:
137 for a in artists:
--> 138 a.draw(renderer)
139 else:
140 # Composite any adjacent images together
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
48 renderer.start_filter()
49
---> 50 return draw(artist, renderer, *args, **kwargs)
51 finally:
52 if artist.get_agg_filter() is not None:
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/mpl/geoaxes.py in draw(self, renderer, inframe)
386
387 return matplotlib.axes.Axes.draw(self, renderer=renderer,
--> 388 inframe=inframe)
389
390 def __str__(self):
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
48 renderer.start_filter()
49
---> 50 return draw(artist, renderer, *args, **kwargs)
51 finally:
52 if artist.get_agg_filter() is not None:
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe)
2626 renderer.stop_rasterizing()
2627
-> 2628 mimage._draw_list_compositing_images(renderer, self, artists)
2629
2630 renderer.close_group('axes')
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
136 if not_composite or not has_images:
137 for a in artists:
--> 138 a.draw(renderer)
139 else:
140 # Composite any adjacent images together
~/anaconda3/envs/sats/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
48 renderer.start_filter()
49
---> 50 return draw(artist, renderer, *args, **kwargs)
51 finally:
52 if artist.get_agg_filter() is not None:
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/mpl/feature_artist.py in draw(self, renderer, *args, **kwargs)
162 except ValueError:
163 warnings.warn('Unable to determine extent. Defaulting to global.')
--> 164 geoms = self._feature.intersecting_geometries(extent)
165
166 # Combine all the keyword args in priority order.
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/feature/__init__.py in intersecting_geometries(self, extent)
301 """
302 self.scaler.scale_from_extent(extent)
--> 303 return super(NaturalEarthFeature, self).intersecting_geometries(extent)
304
305 def with_scale(self, new_scale):
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/feature/__init__.py in intersecting_geometries(self, extent)
118 extent_geom = sgeom.box(extent[0], extent[2],
119 extent[1], extent[3])
--> 120 return (geom for geom in self.geometries() if
121 geom is not None and extent_geom.intersects(geom))
122 else:
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/feature/__init__.py in geometries(self)
285 path = shapereader.natural_earth(resolution=self.scale,
286 category=self.category,
--> 287 name=self.name)
288 geometries = tuple(shapereader.Reader(path).geometries())
289 _NATURAL_EARTH_GEOM_CACHE[key] = geometries
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/io/shapereader.py in natural_earth(resolution, category, name)
357 format_dict = {'config': config, 'category': category,
358 'name': name, 'resolution': resolution}
--> 359 return ne_downloader.path(format_dict)
360
361
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/io/__init__.py in path(self, format_dict)
220 else:
221 # we need to download the file
--> 222 result_path = self.acquire_resource(target_path, format_dict)
223
224 return result_path
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/io/shapereader.py in acquire_resource(self, target_path, format_dict)
412 url = self.url(format_dict)
413
--> 414 shapefile_online = self._urlopen(url)
415
416 zfh = ZipFile(six.BytesIO(shapefile_online.read()), 'r')
~/anaconda3/envs/sats/lib/python3.6/site-packages/cartopy/io/__init__.py in _urlopen(self, url)
259 """
260 warnings.warn('Downloading: {}'.format(url), DownloadWarning)
--> 261 return urlopen(url)
262
263 @staticmethod
~/anaconda3/envs/sats/lib/python3.6/urllib/request.py in urlopen(url, data, timeout, cafile, capath, cadefault, context)
221 else:
222 opener = _opener
--> 223 return opener.open(url, data, timeout)
224
225 def install_opener(opener):
~/anaconda3/envs/sats/lib/python3.6/urllib/request.py in open(self, fullurl, data, timeout)
530 for processor in self.process_response.get(protocol, []):
531 meth = getattr(processor, meth_name)
--> 532 response = meth(req, response)
533
534 return response
~/anaconda3/envs/sats/lib/python3.6/urllib/request.py in http_response(self, request, response)
640 if not (200 <= code < 300):
641 response = self.parent.error(
--> 642 'http', request, response, code, msg, hdrs)
643
644 return response
~/anaconda3/envs/sats/lib/python3.6/urllib/request.py in error(self, proto, *args)
568 if http_err:
569 args = (dict, 'default', 'http_error_default') + orig_args
--> 570 return self._call_chain(*args)
571
572 # XXX probably also want an abstract factory that knows when it makes
~/anaconda3/envs/sats/lib/python3.6/urllib/request.py in _call_chain(self, chain, kind, meth_name, *args)
502 for handler in handlers:
503 func = getattr(handler, meth_name)
--> 504 result = func(*args)
505 if result is not None:
506 return result
~/anaconda3/envs/sats/lib/python3.6/urllib/request.py in http_error_default(self, req, fp, code, msg, hdrs)
648 class HTTPDefaultErrorHandler(BaseHandler):
649 def http_error_default(self, req, fp, code, msg, hdrs):
--> 650 raise HTTPError(req.full_url, code, msg, hdrs, fp)
651
652 class HTTPRedirectHandler(BaseHandler):
HTTPError: HTTP Error 404: Not Found
Full environment definition
So the error occurs because it's trying to download this link, which doesn't work:
http://naciscdn.org/naturalearth/h/physical/ne_h_coastline.zip
The question is...why?
Aha! I think it's this line:
display.plot_ppi_map('reflectivity', 0, resolution = 'h', #The "0" is the lowest PPI scan, increasing this number increases the scanning elevation
vmin=-10, vmax=64, colorbar_flag = False, fig = fig, ax=ax,alpha = .08, projection = crs)
Notice the use of 'h' for resolution--which corresponds to the bad part of the URL. I'm guess this is left over from some Basemap code? Try changing to '10m' or '110m'.
Changing the 'h' to '10m' fixed the issue, should I open an issue with pyart? Thank you for the help though.

It'd probably be nice of them to try to check and issue a more useful error, but that's up to them. Wouldn't hurt to open an issue there to let them know.
I wonder if we should be whitelisting the resolutions here, at least in NaturalEarthFeature class, since we know the currently supported resolutions.
So, the question is where to check:
NaturalEarthFeatureshapereader.natural_earthNEShpDownloaderThoughts anyone? @pelson?
Unfortunately something seems to be wrong at NaturalEarth: https://naciscdn.org/naturalearth/110m/physical/ne_110m_coastline.zip gives a 404 as well.
Just coming to write that same thing. It appears that naciscdn.org is offline right now: https://downforeveryoneorjustme.com/naciscdn.org
Is there a mirror where one can grab these images?
I couldn't find one. I've just switched to GSHHS:
ax.add_feature(cartopy.feature.GSHHSFeature(edgecolor='k'))
You can grab it from their GitHub, though unfortunately due to https://github.com/nvkelso/natural-earth-vector/issues/279 it's not entirely consistent with what's on the site. On Fedora, you can also install one of the natural-earth-map-data packages.
It appears that naciscdn.org has come back up, which should resolve this issue.
Back down for me...
EDIT:
You can grab it from their GitHub, though unfortunately due to nvkelso/natural-earth-vector#279 it's not entirely consistent with what's on the site. On Fedora, you can also install one of the natural-earth-map-data packages.
Is there a way to download the data from GitHub from within Cartopy?
Is there an action item for Cartopy here? Better error/failure messages?
Otherwise, there isn't a whole lot we can do when external websites go down.
External websites aside, the actual bug here is that we need to be more stringent about what's accepted for scale (because h is not valid for NaturalEarth). That's why this is still open.
Most helpful comment
Just coming to write that same thing. It appears that naciscdn.org is offline right now: https://downforeveryoneorjustme.com/naciscdn.org