Skip to content

Instantly share code, notes, and snippets.

@clemenstyp
Last active June 27, 2025 12:06
Show Gist options
  • Save clemenstyp/e6d7c0d29ea25494a3e35e97ae71f5a5 to your computer and use it in GitHub Desktop.
Save clemenstyp/e6d7c0d29ea25494a3e35e97ae71f5a5 to your computer and use it in GitHub Desktop.
## This Python script interacts with the Linkwarden API to manage tags efficiently.
## It provides two main functionalities:
##
## Save Tags: Fetches all tags from your Linkwarden instance and saves them as a CSV file.
## This allows you to easily view and edit tag names and IDs.
## Update Tags: After modifying the CSV file (such as renaming or removing tags), the script updates your
## Linkwarden instance to reflect these changes. Tags not present in the CSV file will be deleted.
##
## To use this script, you need an API token from your Linkwarden settings page.
## Additionally, ensure the requests library is installed (pip install requests).
##
## Run the script with:
##
## python linkwarden_tags.py save to save tags to a CSV file.
## python linkwarden_tags.py update to apply updates from the CSV file to your Linkwarden instance.
import requests
import csv
import sys
API_URL = 'https://<LINKWARDEN_URL>/api/v1/tags'
AUTH_TOKEN = '<YOUR_TOKEN>' # Replace with your actual token
CSV_FILE = 'tags.csv'
def get_tags():
headers = {
'Accept': 'application/json',
'Authorization': f'Bearer {AUTH_TOKEN}'
}
response = requests.get(API_URL, headers=headers)
if response.status_code == 200:
return response.json().get('response', [])
else:
print(f"Error fetching tags: {response.status_code}")
return []
def save_tags_to_csv(tags):
# Sort tags by name
sorted_tags = sorted(tags, key=lambda tag: tag['name'].lower())
with open(CSV_FILE, mode='w', newline='') as file:
writer = csv.writer(file)
writer.writerow(['id', 'name']) # Header
for tag in sorted_tags:
writer.writerow([tag['id'], tag['name']])
def load_tags_from_csv():
tags = []
try:
with open(CSV_FILE, mode='r') as file:
reader = csv.DictReader(file)
for row in reader:
tags.append({'id': int(row['id']), 'name': row['name']})
except FileNotFoundError:
print("CSV file not found. Make sure you have saved tags first.")
return tags
def delete_tags(tags_to_keep):
current_tags = get_tags()
ids_to_keep = {tag['id'] for tag in tags_to_keep}
for tag in current_tags:
if tag['id'] not in ids_to_keep:
delete_tag(tag['id'])
def delete_tag(tag_id):
headers = {
'Accept': 'application/json',
'Authorization': f'Bearer {AUTH_TOKEN}'
}
delete_url = f"{API_URL}/{tag_id}"
response = requests.delete(delete_url, headers=headers)
if response.status_code == 200:
print(f"Tag with ID {tag_id} deleted successfully.")
else:
print(f"Error deleting tag {tag_id}: {response.status_code}")
def update_tags(tags_to_keep):
current_tags = {tag['id']: tag['name'] for tag in get_tags()}
for tag in tags_to_keep:
if tag['id'] in current_tags and current_tags[tag['id']] != tag['name']:
update_tag(tag['id'], tag['name'])
def update_tag(tag_id, new_name):
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': f'Bearer {AUTH_TOKEN}'
}
update_url = f"{API_URL}/{tag_id}"
data = {'name': new_name}
response = requests.put(update_url, headers=headers, json=data)
if response.status_code == 200:
print(f"Tag with ID {tag_id} updated successfully to name '{new_name}'.")
else:
print(f"Error updating tag {tag_id}: {response.status_code}")
def main(action):
if action == 'save':
# Fetch tags and save to CSV
tags = get_tags()
save_tags_to_csv(tags)
print("Tags saved to CSV.")
elif action == 'update':
# Load tags from CSV, update names if changed, and delete tags not in CSV
tags_to_keep = load_tags_from_csv()
update_tags(tags_to_keep)
delete_tags(tags_to_keep)
else:
print("Invalid action. Use 'save' or 'update'.")
if __name__ == '__main__':
if len(sys.argv) != 2:
print("Usage: python linkwarden_tags.py [save|update]")
else:
main(sys.argv[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment