# arcgis-notebooks > Write Python code for ArcGIS Online Notebooks. Use when asked to query, update, or manage Feature Layers, manipulate Web Maps, export data, or perform any arcgis API operations in a hosted notebook environment. Covers authentication, pagination, Spatially Enabled DataFrames, edit_features batching, and content management. - Author: Jeff Franzen - Repository: franzenjb/claude-skills - Version: 20260206183911 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-07 - Source: https://github.com/franzenjb/claude-skills - Web: https://mule.run/skillshub/@@franzenjb/claude-skills~arcgis-notebooks:20260206183911 --- --- name: arcgis-notebooks description: Write Python code for ArcGIS Online Notebooks. Use when asked to query, update, or manage Feature Layers, manipulate Web Maps, export data, or perform any arcgis API operations in a hosted notebook environment. Covers authentication, pagination, Spatially Enabled DataFrames, edit_features batching, and content management. --- # ArcGIS Online Notebooks ## Authentication Always use notebook-native authentication: ```python from arcgis.gis import GIS gis = GIS("home") # NEVER use credentials in notebooks print(f"Connected as: {gis.users.me.username}") ``` ## Feature Layer Operations ### Query with Pagination (Large Datasets) ```python from arcgis.features import FeatureLayer import pandas as pd fl = FeatureLayer("https://services.arcgis.com/.../FeatureServer/0", gis=gis) count = fl.query(return_count_only=True) if count > 10000: all_data = [] offset = 0 while offset < count: chunk = fl.query(result_offset=offset, result_record_count=5000).sdf all_data.append(chunk) offset += 5000 df = pd.concat(all_data, ignore_index=True) else: df = fl.query(where="1=1", return_all_records=True).sdf ``` ### Update Features in Chunks ```python def push_updates(fl, df, key_field, chunk_size=200): """Update feature attributes from DataFrame, matching on key_field.""" features = fl.query(where="1=1", out_fields="*").features df_indexed = df.set_index(key_field) updates = [] for ft in features: key = ft.attributes.get(key_field) if key in df_indexed.index: row = df_indexed.loc[key] for col, val in row.items(): if col != key_field: ft.attributes[col] = None if pd.isna(val) else val updates.append(ft) if len(updates) >= chunk_size: result = fl.edit_features(updates=updates) print(f"Updated {len(updates)} features") updates = [] if updates: fl.edit_features(updates=updates) ``` ### Add New Features ```python from arcgis.features import Feature from arcgis.geometry import Point new_features = [ Feature(geometry=Point({"x": -77.0, "y": 38.9, "spatialReference": {"wkid": 4326}}), attributes={"name": "DC Office", "status": "Active"}) ] fl.edit_features(adds=new_features) ``` ### Delete Features ```python # By OID fl.edit_features(deletes="1,2,3") # By query oids = fl.query(where="status='Inactive'", return_ids_only=True)['objectIds'] if oids: fl.edit_features(deletes=",".join(map(str, oids))) ``` ## Web Map Manipulation ```python import copy import json item = gis.content.get("ITEM_ID") webmap_data = item.get_data() # Returns dict, not JSON string # Modify operational layers for layer in webmap_data.get('operationalLayers', []): layer['visibility'] = False # Group layers have nested 'layers' for sublayer in layer.get('layers', []): sublayer['visibility'] = True # Save changes item.update(data=json.dumps(webmap_data)) # Or create new map new_data = copy.deepcopy(webmap_data) props = { 'title': 'New Map', 'type': 'Web Map', 'tags': 'auto-generated', 'text': json.dumps(new_data) } new_item = gis.content.add(item_properties=props) ``` ## Content Management ```python # Search with proper escaping results = gis.content.search( f'title:"{title}" owner:{gis.users.me.username} type:"Web Map"' ) # Check exists before create if results: results[0].update(data=json.dumps(new_data)) else: gis.content.add(item_properties=props) # Move to folder item.move(folder="Analysis Results") # Share item.share(org=True) # or groups=['group_id'] ``` ## Common Gotchas - `get_data()` returns dict, not string — use `json.dumps()` when saving - `edit_features()` silently fails on mismatched field names — verify field names first - NaN values must be converted to `None` before updating - Chunk writes to avoid timeouts (200 features per batch is safe) - Always pass `gis=gis` to FeatureLayer if using secured services - `return_all_records=True` can timeout on large datasets — use pagination instead