2025-09-08 00:49:34 +00:00

4485 lines
177 KiB
HTML

<!DOCTYPE html><html lang="en" class="no-js"><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="Stash documentation, guides, plugins and support.">
<link rel="canonical" href="https://docs.stashapp.cc/in-app-manual/scraping/scraperdevelopment/">
<link rel="prev" href="../">
<link rel="next" href="../../plugins/">
<link rel="icon" href="../../../assets/images/favicon.ico">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.19">
<title>Contributing scrapers - Stash-Docs</title>
<link rel="stylesheet" href="../../../assets/stylesheets/main.7e37652d.min.css">
<link rel="stylesheet" href="../../../assets/stylesheets/palette.06af60db.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&amp;display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<link rel="stylesheet" href="../../../stylesheets/extra.css">
<script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
<meta property="og:type" content="website">
<meta property="og:title" content="Contributing scrapers - Stash-Docs">
<meta property="og:description" content="Stash documentation, guides, plugins and support.">
<meta property="og:image" content="https://docs.stashapp.cc/assets/images/social/in-app-manual/scraping/scraperdevelopment.png">
<meta property="og:image:type" content="image/png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:url" content="https://docs.stashapp.cc/in-app-manual/scraping/scraperdevelopment/">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Contributing scrapers - Stash-Docs">
<meta name="twitter:description" content="Stash documentation, guides, plugins and support.">
<meta name="twitter:image" content="https://docs.stashapp.cc/assets/images/social/in-app-manual/scraping/scraperdevelopment.png">
<link rel="stylesheet" href="../../../assets/stylesheets/announce.css">
<link href="../../../assets/stylesheets/glightbox.min.css" rel="stylesheet"><script src="../../../assets/javascripts/glightbox.min.js"></script><style id="glightbox-style">
html.glightbox-open { overflow: initial; height: 100%; }
.gslide-title { margin-top: 0px; user-select: text; }
.gslide-desc { color: #666; user-select: text; }
.gslide-image img { background: white; }
.gscrollbar-fixer { padding-right: 15px; }
.gdesc-inner { font-size: 0.75rem; }
body[data-md-color-scheme="slate"] .gdesc-inner { background: var(--md-default-bg-color); }
body[data-md-color-scheme="slate"] .gslide-title { color: var(--md-default-fg-color); }
body[data-md-color-scheme="slate"] .gslide-desc { color: var(--md-default-fg-color); }
</style></head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#contributing-scrapers" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
<aside class="md-banner">
<div class="md-banner__inner md-grid md-typeset">
<button class="md-banner__button md-icon" aria-label="Don't show this again">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></svg>
</button>
<span class="twemoji heart"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill="currentColor" d="m241 87.1 15 20.7 15-20.7C296 52.5 336.2 32 378.9 32 452.4 32 512 91.6 512 165.1v2.6c0 112.2-139.9 242.5-212.9 298.2-12.4 9.4-27.6 14.1-43.1 14.1s-30.8-4.6-43.1-14.1C139.9 410.2 0 279.9 0 167.7v-2.6C0 91.6 59.6 32 133.1 32 175.8 32 216 52.5 241 87.1"></path></svg></span>
Support continued development via
<a href="https://opencollective.com/stashapp">
<span class="twemoji mastodon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12c2.54 0 4.894-.79 6.834-2.135l-3.107-3.109a7.715 7.715 0 1 1 0-13.512l3.107-3.109A11.94 11.94 0 0 0 12 0m9.865 5.166-3.109 3.107A7.7 7.7 0 0 1 19.715 12a7.7 7.7 0 0 1-.959 3.727l3.109 3.107A11.94 11.94 0 0 0 24 12c0-2.54-.79-4.894-2.135-6.834"></path></svg>
</span>
OpenCollective donation</a>
or
<a href="https://github.com/sponsors/stashapp">
<span class="twemoji mastodon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"></path></svg>
</span>
GitHub sponsorship</a>
</div>
<script>var el=document.querySelector("[data-md-component=announce]");if(el){var content=el.querySelector(".md-typeset");__md_hash(content.innerHTML)===__md_get("__announce")&&(el.hidden=!0)}</script>
</aside>
</div>
<header class="md-header" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="../../.." title="Stash-Docs" class="md-header__button md-logo" aria-label="Stash-Docs" data-md-component="logo">
<img src="../../../assets/images/logo_white.svg" alt="logo">
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"></path></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
Stash-Docs
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Contributing scrapers
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"></path></svg>
</label>
<input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"></path></svg>
</label>
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"></path></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"></path></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"></path></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"></path></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></svg>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://github.com/stashapp/Stash-Docs" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill="currentColor" d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"></path></svg>
</div>
<div class="md-source__repository">
stashapp/Stash-Docs
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="../../.." class="md-tabs__link">
Home
</a>
</li>
<li class="md-tabs__item">
<a href="../../../installation/" class="md-tabs__link">
Installation
</a>
</li>
<li class="md-tabs__item md-tabs__item--active">
<a href="../../" class="md-tabs__link">
In-app manual
</a>
</li>
<li class="md-tabs__item">
<a href="../../../guides/" class="md-tabs__link">
Guides
</a>
</li>
<li class="md-tabs__item">
<a href="../../../metadata-sources/" class="md-tabs__link">
Metadata sources
</a>
</li>
<li class="md-tabs__item">
<a href="../../../plugins/" class="md-tabs__link">
Plugins
</a>
</li>
<li class="md-tabs__item">
<a href="../../../api/" class="md-tabs__link">
API
</a>
</li>
<li class="md-tabs__item">
<a href="https://discourse.stashapp.cc" class="md-tabs__link">
Community forum
</a>
</li>
<li class="md-tabs__item">
<a href="../../../code-of-conduct/" class="md-tabs__link">
Code of conduct
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="../../.." title="Stash-Docs" class="md-nav__button md-logo" aria-label="Stash-Docs" data-md-component="logo">
<img src="../../../assets/images/logo_white.svg" alt="logo">
</a>
Stash-Docs
</label>
<div class="md-nav__source">
<a href="https://github.com/stashapp/Stash-Docs" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill="currentColor" d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"></path></svg>
</div>
<div class="md-source__repository">
stashapp/Stash-Docs
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../.." class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2">
<div class="md-nav__link md-nav__container">
<a href="../../../installation/" class="md-nav__link ">
<span class="md-ellipsis">
Installation
</span>
</a>
<label class="md-nav__link " for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Installation
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../installation/windows/" class="md-nav__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill="currentColor" d="m0 93.7 183.6-25.3v177.4H0zm0 324.6 183.6 25.3V268.4H0zm203.8 28L448 480V268.4H203.8zm0-380.6v180.1H448V32z"></path></svg>
<span class="md-ellipsis">
Windows
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../installation/macos/" class="md-nav__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill="currentColor" d="M319.1 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7-55.8.9-115.1 44.5-115.1 133.2 0 26.2 4.8 53.3 14.4 81.2 12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9m-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3"></path></svg>
<span class="md-ellipsis">
macOS
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../installation/linux/" class="md-nav__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill="currentColor" d="M220.9 123.3c1 .5 1.8 1.7 3 1.7 1.1 0 2.8-.4 2.9-1.5.2-1.4-1.9-2.3-3.2-2.9-1.7-.7-3.9-1-5.5-.1-.4.2-.8.7-.6 1.1.3 1.3 2.3 1.1 3.4 1.7M199 125c1.2 0 2-1.2 3-1.7 1.1-.6 3.1-.4 3.5-1.6.2-.4-.2-.9-.6-1.1-1.6-.9-3.8-.6-5.5.1-1.3.6-3.4 1.5-3.2 2.9.1 1 1.8 1.5 2.8 1.4m221 278.8c-3.6-4-5.3-11.6-7.2-19.7-1.8-8.1-3.9-16.8-10.5-22.4-1.3-1.1-2.6-2.1-4-2.9-1.3-.8-2.7-1.5-4.1-2 9.2-27.3 5.6-54.5-3.7-79.1-11.4-30.1-31.3-56.4-46.5-74.4-17.1-21.5-33.7-41.9-33.4-72C311.1 85.4 315.7.1 234.8 0 132.4-.2 158 103.4 156.9 135.2c-1.7 23.4-6.4 41.8-22.5 64.7-18.9 22.5-45.5 58.8-58.1 96.7-6 17.9-8.8 36.1-6.2 53.3-6.5 5.8-11.4 14.7-16.6 20.2-4.2 4.3-10.3 5.9-17 8.3s-14 6-18.5 14.5c-2.1 3.9-2.8 8.1-2.8 12.4 0 3.9.6 7.9 1.2 11.8 1.2 8.1 2.5 15.7.8 20.8-5.2 14.4-5.9 24.4-2.2 31.7 3.8 7.3 11.4 10.5 20.1 12.3 17.3 3.6 40.8 2.7 59.3 12.5 19.8 10.4 39.9 14.1 55.9 10.4 11.6-2.6 21.1-9.6 25.9-20.2 12.5-.1 26.3-5.4 48.3-6.6 14.9-1.2 33.6 5.3 55.1 4.1.6 2.3 1.4 4.6 2.5 6.7v.1c8.3 16.7 23.8 24.3 40.3 23 16.6-1.3 34.1-11 48.3-27.9 13.6-16.4 36-23.2 50.9-32.2 7.4-4.5 13.4-10.1 13.9-18.3.4-8.2-4.4-17.3-15.5-29.7M223.8 87.3c9.8-22.2 34.2-21.8 44-.4 6.5 14.2 3.6 30.9-4.3 40.4-1.6-.8-5.9-2.6-12.6-4.9 1.1-1.2 3.1-2.7 3.9-4.6 4.8-11.8-.2-27-9.1-27.3-7.3-.5-13.9 10.8-11.8 23-4.1-2-9.4-3.5-13-4.4-1-6.9-.3-14.6 2.9-21.8m-40.7-11.5c10.1 0 20.8 14.2 19.1 33.5-3.5 1-7.1 2.5-10.2 4.6 1.2-8.9-3.3-20.1-9.6-19.6-8.4.7-9.8 21.2-1.8 28.1 1 .8 1.9-.2-5.9 5.5-15.6-14.6-10.5-52.1 8.4-52.1m-13.6 60.7c6.2-4.6 13.6-10 14.1-10.5 4.7-4.4 13.5-14.2 27.9-14.2 7.1 0 15.6 2.3 25.9 8.9 6.3 4.1 11.3 4.4 22.6 9.3 8.4 3.5 13.7 9.7 10.5 18.2-2.6 7.1-11 14.4-22.7 18.1-11.1 3.6-19.8 16-38.2 14.9-3.9-.2-7-1-9.6-2.1-8-3.5-12.2-10.4-20-15-8.6-4.8-13.2-10.4-14.7-15.3q-2.1-7.35 4.2-12.3m3.3 334c-2.7 35.1-43.9 34.4-75.3 18-29.9-15.8-68.6-6.5-76.5-21.9-2.4-4.7-2.4-12.7 2.6-26.4v-.2c2.4-7.6.6-16-.6-23.9-1.2-7.8-1.8-15 .9-20 3.5-6.7 8.5-9.1 14.8-11.3 10.3-3.7 11.8-3.4 19.6-9.9 5.5-5.7 9.5-12.9 14.3-18 5.1-5.5 10-8.1 17.7-6.9 8.1 1.2 15.1 6.8 21.9 16l19.6 35.6c9.5 19.9 43.1 48.4 41 68.9m-1.4-25.9c-4.1-6.6-9.6-13.6-14.4-19.6 7.1 0 14.2-2.2 16.7-8.9 2.3-6.2 0-14.9-7.4-24.9-13.5-18.2-38.3-32.5-38.3-32.5-13.5-8.4-21.1-18.7-24.6-29.9s-3-23.3-.3-35.2c5.2-22.9 18.6-45.2 27.2-59.2 2.3-1.7.8 3.2-8.7 20.8-8.5 16.1-24.4 53.3-2.6 82.4.6-20.7 5.5-41.8 13.8-61.5 12-27.4 37.3-74.9 39.3-112.7 1.1.8 4.6 3.2 6.2 4.1 4.6 2.7 8.1 6.7 12.6 10.3 12.4 10 28.5 9.2 42.4 1.2 6.2-3.5 11.2-7.5 15.9-9 9.9-3.1 17.8-8.6 22.3-15 7.7 30.4 25.7 74.3 37.2 95.7 6.1 11.4 18.3 35.5 23.6 64.6 3.3-.1 7 .4 10.9 1.4 13.8-35.7-11.7-74.2-23.3-84.9-4.7-4.6-4.9-6.6-2.6-6.5 12.6 11.2 29.2 33.7 35.2 59 2.8 11.6 3.3 23.7.4 35.7 16.4 6.8 35.9 17.9 30.7 34.8-2.2-.1-3.2 0-4.2 0 3.2-10.1-3.9-17.6-22.8-26.1-19.6-8.6-36-8.6-38.3 12.5-12.1 4.2-18.3 14.7-21.4 27.3-2.8 11.2-3.6 24.7-4.4 39.9-.5 7.7-3.6 18-6.8 29-32.1 22.9-76.7 32.9-114.3 7.2m257.4-11.5c-.9 16.8-41.2 19.9-63.2 46.5-13.2 15.7-29.4 24.4-43.6 25.5s-26.5-4.8-33.7-19.3c-4.7-11.1-2.4-23.1 1.1-36.3 3.7-14.2 9.2-28.8 9.9-40.6.8-15.2 1.7-28.5 4.2-38.7 2.6-10.3 6.6-17.2 13.7-21.1.3-.2.7-.3 1-.5.8 13.2 7.3 26.6 18.8 29.5 12.6 3.3 30.7-7.5 38.4-16.3 9-.3 15.7-.9 22.6 5.1 9.9 8.5 7.1 30.3 17.1 41.6 10.6 11.6 14 19.5 13.7 24.6M173.4 148.7c2 1.9 4.7 4.5 8 7.1 6.6 5.2 15.8 10.6 27.3 10.6 11.6 0 22.5-5.9 31.8-10.8 4.9-2.6 10.9-7 14.8-10.4s5.9-6.3 3.1-6.6-2.6 2.6-6 5.1c-4.4 3.2-9.7 7.4-13.9 9.8-7.4 4.2-19.5 10.2-29.9 10.2s-18.7-4.8-24.9-9.7c-3.1-2.5-5.7-5-7.7-6.9-1.5-1.4-1.9-4.6-4.3-4.9-1.4-.1-1.8 3.7 1.7 6.5"></path></svg>
<span class="md-ellipsis">
Linux
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../installation/docker/" class="md-nav__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill="currentColor" d="M349.9 236.3h-66.1v-59.4h66.1zm0-204.3h-66.1v60.7h66.1zm78.2 144.8H362v59.4h66.1zm-156.3-72.1h-66.1v60.1h66.1zm78.1 0h-66.1v60.1h66.1zm276.8 100c-14.4-9.7-47.6-13.2-73.1-8.4-3.3-24-16.7-44.9-41.1-63.7l-14-9.3-9.3 14c-18.4 27.8-23.4 73.6-3.7 103.8-8.7 4.7-25.8 11.1-48.4 10.7H2.4c-8.7 50.8 5.8 116.8 44 162.1 37.1 43.9 92.7 66.2 165.4 66.2 157.4 0 273.9-72.5 328.4-204.2 21.4.4 67.6.1 91.3-45.2 1.5-2.5 6.6-13.2 8.5-17.1zm-511.1-27.9h-66v59.4h66.1v-59.4zm78.1 0h-66.1v59.4h66.1zm78.1 0h-66.1v59.4h66.1zm-78.1-72.1h-66.1v60.1h66.1z"></path></svg>
<span class="md-ellipsis">
Docker
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../installation/synology/" class="md-nav__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m13.44 8.927-.889.37.056.117a.6.6 0 0 1 .212-.054q.076.001.126.046.05.042.072.16.022.119.022.634v2.736q0 .284-.042.381a.3.3 0 0 1-.118.142q-.079.046-.286.045v.12h1.481v-.12q-.231 0-.32-.048a.3.3 0 0 1-.126-.142q-.04-.09-.04-.378V8.927zm-11.722.34q-.494 0-.84.147-.35.15-.534.436a1.1 1.1 0 0 0-.185.612q0 .508.393.864.276.252.968.422.537.135.688.191a.7.7 0 0 1 .31.183q.087.106.088.259 0 .232-.21.41-.212.175-.628.176-.393 0-.625-.197-.23-.199-.307-.619L0 12.23q.084.72.517 1.096.434.378 1.244.378.556-.002.93-.156a1.26 1.26 0 0 0 .781-1.169 1.3 1.3 0 0 0-.171-.684 1.2 1.2 0 0 0-.472-.437q-.3-.16-.927-.31-.628-.147-.79-.286a.326.326 0 0 1 .009-.524q.21-.157.586-.156.361 0 .542.145.181.147.237.471l.864-.028q-.019-.591-.425-.949-.407-.353-1.208-.353zm21.808.33a.475.475 0 1 0-.002.95.475.475 0 0 0 .002-.95m0 .072a.4.4 0 0 1 .401.403c0 .116-.05.22-.128.294l-.086-.135a.4.4 0 0 0-.065-.078.2.2 0 0 0-.048-.03.2.2 0 0 0 .127-.057.14.14 0 0 0 .043-.109.2.2 0 0 0-.025-.091.13.13 0 0 0-.067-.055.3.3 0 0 0-.123-.02h-.266v.606h.08v-.268h.091q.03 0 .045.003.02.005.036.014.018.014.04.043.023.03.059.083l.08.125h.043a.4.4 0 0 1-.237.08.405.405 0 0 1-.404-.405c0-.224.18-.403.404-.403m-.157.191h.191q.067 0 .097.027a.09.09 0 0 1 .03.07.1.1 0 0 1-.016.055.08.08 0 0 1-.047.035.2.2 0 0 1-.085.013h-.17zm-15.037.6q-.616-.001-1.023.514v-.455h-.754v3.105h.814v-1.401c0-.348.022-.583.063-.713a.6.6 0 0 1 .234-.306.67.67 0 0 1 .385-.118q.167 0 .287.082.119.08.17.229.055.148.054.646v1.581h.816V11.7a2.5 2.5 0 0 0-.046-.55.9.9 0 0 0-.16-.343.83.83 0 0 0-.341-.25 1.3 1.3 0 0 0-.499-.097m2.65 0a1.7 1.7 0 0 0-.826.2 1.4 1.4 0 0 0-.571.586 1.7 1.7 0 0 0-.202.793q0 .534.202.904.201.374.588.566.388.194.814.194.69-.001 1.144-.463.455-.464.455-1.167 0-.697-.451-1.156-.449-.457-1.154-.457zm7.315.05q-.527 0-.865.323a1.02 1.02 0 0 0-.336.77q0 .29.147.534c.1.162.24.285.423.379q-.334.281-.429.44a.55.55 0 0 0-.092.271q0 .102.071.184t.24.187a10 10 0 0 0-.329.355c-.113.145-.19.253-.226.336a.4.4 0 0 0-.034.157q0 .178.246.343.437.284 1.071.284.825 0 1.337-.477.349-.326.35-.694a.61.61 0 0 0-.183-.45.84.84 0 0 0-.49-.227 9 9 0 0 0-.878-.053 4 4 0 0 1-.46-.027q-.159-.023-.212-.075-.056-.054-.056-.112a.4.4 0 0 1 .05-.159.9.9 0 0 1 .186-.221q.234.072.459.07.54 0 .864-.301a.96.96 0 0 0 .323-.722q0-.37-.187-.61h.394c.097 0 .15-.002.167-.01a.06.06 0 0 0 .035-.025.3.3 0 0 0 .018-.12.2.2 0 0 0-.02-.105.1.1 0 0 0-.033-.028 1 1 0 0 0-.166-.008h-.639a1.3 1.3 0 0 0-.746-.21zm-2.752 0q-.378 0-.714.194a1.44 1.44 0 0 0-.546.61 1.8 1.8 0 0 0-.205.825q0 .571.34 1.03a1.29 1.29 0 0 0 1.09.543q.419 0 .76-.211.344-.21.54-.627.194-.414.194-.821 0-.577-.354-1.022a1.34 1.34 0 0 0-1.105-.522zm-12.182.009 1.174 3.113a1.2 1.2 0 0 1-.21.431q-.135.168-.419.167-.154 0-.344-.04l.067.645q.228.05.464.052.232-.001.418-.052a1 1 0 0 0 .31-.138.9.9 0 0 0 .224-.234 2.2 2.2 0 0 0 .205-.414l.199-.545 1.085-2.985h-.844l-.722 2.204-.74-2.204zm16.631.078v.122a.8.8 0 0 1 .245.091q.052.043.136.157.108.152.158.255l1.088 2.275-.213.526q-.119.292-.236.393-.118.103-.217.104a1 1 0 0 1-.167-.05 1 1 0 0 0-.3-.07c-.105 0-.19.025-.25.084a.29.29 0 0 0-.092.22q0 .146.126.257a.46.46 0 0 0 .322.112q.27.002.56-.223.29-.224.469-.664l1.226-3.014a1.6 1.6 0 0 1 .113-.254.6.6 0 0 1 .145-.146.5.5 0 0 1 .188-.053v-.122h-.978v.122q.14 0 .197.023a.17.17 0 0 1 .083.057.15.15 0 0 1 .023.087q0 .136-.056.271l-.675 1.671-.737-1.53q-.11-.225-.11-.356a.21.21 0 0 1 .074-.16.35.35 0 0 1 .224-.063h.068v-.122zm-1.753.08q.26.001.43.217.224.293.224.815 0 .398-.16.584a.52.52 0 0 1-.41.188.53.53 0 0 1-.43-.216q-.223-.286-.223-.802c0-.268.054-.461.163-.59a.52.52 0 0 1 .406-.197zm-2.798.054q.362-.002.598.312.346.46.346 1.263 0 .643-.209.905a.65.65 0 0 1-.528.264q-.429-.002-.691-.477c-.174-.32-.263-.695-.263-1.135q0-.406.11-.669a.73.73 0 0 1 .285-.361.67.67 0 0 1 .352-.102m-4.463.395q.323.001.543.247.216.244.216.703 0 .468-.216.712a.7.7 0 0 1-.543.248.7.7 0 0 1-.542-.248q-.22-.242-.22-.708 0-.463.22-.707a.7.7 0 0 1 .542-.247m6.66 2.498q.398.056 1.142.08.51.01.68.083t.17.241q0 .235-.282.442-.284.208-.874.208-.622-.001-.951-.204-.191-.115-.19-.277c0-.078.024-.169.076-.26a1.5 1.5 0 0 1 .228-.313z"></path></svg>
<span class="md-ellipsis">
Synology
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../installation/freenas-truenas/" class="md-nav__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M24 10.049v5.114l-10.949 6.324v-5.114zm-24 0v5.114l10.956 6.324v-5.114zm12.004-.605-4.433 2.559 4.433 2.559 4.429-2.559zm10.952-1.207-9.905-5.723v5.118l5.473 3.164zm-12-.605V2.513L1.044 8.236l4.432 2.555z"></path></svg>
<span class="md-ellipsis">
FreeNAS/TrueNAS
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../installation/unraid/" class="md-nav__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M11.406 8.528h1.17v6.926h-1.17zM1.17 15.454H0V8.528h1.17zm4.534.828h1.17v2.645h-1.17zm-2.86-2.969h1.169v4.282h-1.17zm5.703 0h1.17v4.282h-1.17zM22.83 8.528H24v6.926h-1.17zm-4.534-.81h-1.17V5.073h1.17zm2.86 2.95h-1.169V6.406h1.17zm-5.72 0h-1.17V6.406h1.17z"></path></svg>
<span class="md-ellipsis">
Unraid
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_9">
<label class="md-nav__link" for="__nav_2_9" id="__nav_2_9_label" tabindex="0">
<span class="md-ellipsis">
Getting started
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_9_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2_9">
<span class="md-nav__icon md-icon"></span>
Getting started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../getting-started/first-steps/" class="md-nav__link">
<span class="md-ellipsis">
First steps
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<div class="md-nav__link md-nav__container">
<a href="../../" class="md-nav__link ">
<span class="md-ellipsis">
In-app manual
</span>
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
In-app manual
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../introduction/" class="md-nav__link">
<span class="md-ellipsis">
Introduction
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../configuration/" class="md-nav__link">
<span class="md-ellipsis">
Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../interface/" class="md-nav__link">
<span class="md-ellipsis">
Interface options
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5">
<div class="md-nav__link md-nav__container">
<a href="../../tasks/" class="md-nav__link ">
<span class="md-ellipsis">
Tasks
</span>
</a>
<label class="md-nav__link " for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Tasks
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../tasks/identify/" class="md-nav__link">
<span class="md-ellipsis">
Identify
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../tasks/autotagging/" class="md-nav__link">
<span class="md-ellipsis">
Auto tagging
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../tasks/scenefilenameparser/" class="md-nav__link">
<span class="md-ellipsis">
Scene filename parser
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../tasks/jsonspec/" class="md-nav__link">
<span class="md-ellipsis">
Import/export JSON specification
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../../browsing/" class="md-nav__link">
<span class="md-ellipsis">
Browsing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../images/" class="md-nav__link">
<span class="md-ellipsis">
Images and galleries
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_8" checked>
<div class="md-nav__link md-nav__container">
<a href="../" class="md-nav__link ">
<span class="md-ellipsis">
Metadata scraping
</span>
</a>
<label class="md-nav__link " for="__nav_3_8" id="__nav_3_8_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_8_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_8">
<span class="md-nav__icon md-icon"></span>
Metadata scraping
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Contributing scrapers
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Contributing scrapers
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#xpath-scraper-templates" class="md-nav__link">
<span class="md-ellipsis">
XPath scraper templates
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scraper-configuration-file-format" class="md-nav__link">
<span class="md-ellipsis">
Scraper configuration file format
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#actions" class="md-nav__link">
<span class="md-ellipsis">
Actions
</span>
</a>
<nav class="md-nav" aria-label="Actions">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#script" class="md-nav__link">
<span class="md-ellipsis">
Script
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scrapexpath" class="md-nav__link">
<span class="md-ellipsis">
scrapeXPath
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scrapejson" class="md-nav__link">
<span class="md-ellipsis">
scrapeJson
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scrapexpath-and-scrapejson-use-with-performerbyname" class="md-nav__link">
<span class="md-ellipsis">
scrapeXPath and scrapeJson use with performerByName
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scrapexpath-and-scrapejson-use-with-scenebyfragment-and-scenebyqueryfragment" class="md-nav__link">
<span class="md-ellipsis">
scrapeXPath and scrapeJson use with sceneByFragment and sceneByQueryFragment
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scrapexpath-and-scrapejson-use-with-sceneperformergallerygroupbyurl" class="md-nav__link">
<span class="md-ellipsis">
scrapeXPath and scrapeJson use with &lt;scene|performer|gallery|group&gt;ByURL
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#stash" class="md-nav__link">
<span class="md-ellipsis">
Stash
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#xpath-and-json-scrapers-configuration" class="md-nav__link">
<span class="md-ellipsis">
Xpath and JSON scrapers configuration
</span>
</a>
<nav class="md-nav" aria-label="Xpath and JSON scrapers configuration">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#fixed-attribute-values" class="md-nav__link">
<span class="md-ellipsis">
Fixed attribute values
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#common-fragments" class="md-nav__link">
<span class="md-ellipsis">
Common fragments
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#post-processing-options" class="md-nav__link">
<span class="md-ellipsis">
Post-processing options
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#xpath-resources" class="md-nav__link">
<span class="md-ellipsis">
XPath resources:
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#gjson-resources" class="md-nav__link">
<span class="md-ellipsis">
GJSON resources:
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#debugging-support" class="md-nav__link">
<span class="md-ellipsis">
Debugging support
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#cdp-support" class="md-nav__link">
<span class="md-ellipsis">
CDP support
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#cdp-click-support" class="md-nav__link">
<span class="md-ellipsis">
CDP Click support
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#cookie-support" class="md-nav__link">
<span class="md-ellipsis">
Cookie support
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#headers" class="md-nav__link">
<span class="md-ellipsis">
Headers
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#xpath-scraper-example" class="md-nav__link">
<span class="md-ellipsis">
XPath scraper example
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#json-scraper-example" class="md-nav__link">
<span class="md-ellipsis">
JSON scraper example
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#object-fields" class="md-nav__link">
<span class="md-ellipsis">
Object fields
</span>
</a>
<nav class="md-nav" aria-label="Object fields">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#gallery" class="md-nav__link">
<span class="md-ellipsis">
Gallery
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#group" class="md-nav__link">
<span class="md-ellipsis">
Group
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#image" class="md-nav__link">
<span class="md-ellipsis">
Image
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#performer" class="md-nav__link">
<span class="md-ellipsis">
Performer
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scene" class="md-nav__link">
<span class="md-ellipsis">
Scene
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#studio" class="md-nav__link">
<span class="md-ellipsis">
Studio
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#tag" class="md-nav__link">
<span class="md-ellipsis">
Tag
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_9">
<div class="md-nav__link md-nav__container">
<a href="../../plugins/" class="md-nav__link ">
<span class="md-ellipsis">
Plugins
</span>
</a>
<label class="md-nav__link " for="__nav_3_9" id="__nav_3_9_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_9_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_9">
<span class="md-nav__icon md-icon"></span>
Plugins
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../plugins/externalplugins/" class="md-nav__link">
<span class="md-ellipsis">
External plugins
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../plugins/embeddedplugins/" class="md-nav__link">
<span class="md-ellipsis">
Embedded plugins
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../plugins/uipluginapi/" class="md-nav__link">
<span class="md-ellipsis">
UI plugin API
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../../tagger/" class="md-nav__link">
<span class="md-ellipsis">
Scene tagger
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../deduplication/" class="md-nav__link">
<span class="md-ellipsis">
Dupe checker
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../interactive/" class="md-nav__link">
<span class="md-ellipsis">
Interactivity
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../captions/" class="md-nav__link">
<span class="md-ellipsis">
Captions
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../keyboardshortcuts/" class="md-nav__link">
<span class="md-ellipsis">
Keyboard shortcuts
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../contributing/" class="md-nav__link">
<span class="md-ellipsis">
Ways to contribute
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4">
<div class="md-nav__link md-nav__container">
<a href="../../../guides/" class="md-nav__link ">
<span class="md-ellipsis">
Guides
</span>
</a>
<label class="md-nav__link " for="__nav_4" id="__nav_4_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
Guides
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../guides/scraping-scenes-via-stash-box/" class="md-nav__link">
<span class="md-ellipsis">
Scraping scenes via stash-box
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../guides/backup-and-restore-database/" class="md-nav__link">
<span class="md-ellipsis">
Backup and restore database
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../guides/reverse-proxy/" class="md-nav__link">
<span class="md-ellipsis">
Reverse proxy
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../guides/troubleshooting-video-playback/" class="md-nav__link">
<span class="md-ellipsis">
Troubleshooting video playback
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../guides/run-cdp-on-truenas-scale/" class="md-nav__link">
<span class="md-ellipsis">
Run CDP on TrueNAS Scale
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../guides/advanced-configuration-options/" class="md-nav__link">
<span class="md-ellipsis">
Advanced configuration options
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../guides/importing-via-csv-using-gql-iterate/" class="md-nav__link">
<span class="md-ellipsis">
Bulk importing via CSV using gql-iterate
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../guides/manually-editing-the-stash-sqlite3-database/" class="md-nav__link">
<span class="md-ellipsis">
Manually editing the Stash sqlite3 database
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../guides/scraping-metadata-behind-login/" class="md-nav__link">
<span class="md-ellipsis">
Scraping metadata behind login
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5">
<div class="md-nav__link md-nav__container">
<a href="../../../metadata-sources/" class="md-nav__link ">
<span class="md-ellipsis">
Metadata sources
</span>
</a>
<label class="md-nav__link " for="__nav_5" id="__nav_5_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Metadata sources
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../metadata-sources/stash-box-instances/" class="md-nav__link">
<span class="md-ellipsis">
stash-box instances
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../metadata-sources/scrapers/" class="md-nav__link">
<span class="md-ellipsis">
Scrapers
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../metadata-sources/list/" class="md-nav__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2m6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.75.75 0 0 1-1.042-.018.75.75 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1"></path></svg>
<span class="md-ellipsis">
Browse scrapers
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6">
<div class="md-nav__link md-nav__container">
<a href="../../../plugins/" class="md-nav__link ">
<span class="md-ellipsis">
Plugins
</span>
</a>
<label class="md-nav__link " for="__nav_6" id="__nav_6_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
Plugins
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../plugins/list/" class="md-nav__link">
<span class="md-ellipsis">
Browse plugins
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6_3">
<div class="md-nav__link md-nav__container">
<a href="../../../themes/" class="md-nav__link ">
<span class="md-ellipsis">
Themes
</span>
</a>
<label class="md-nav__link " for="__nav_6_3" id="__nav_6_3_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_6_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6_3">
<span class="md-nav__icon md-icon"></span>
Themes
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../themes/list/" class="md-nav__link">
<span class="md-ellipsis">
Browse themes
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../themes/custom-css-snippets/" class="md-nav__link">
<span class="md-ellipsis">
Custom CSS snippets
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6_4">
<div class="md-nav__link md-nav__container">
<a href="../../../userscripts/" class="md-nav__link ">
<span class="md-ellipsis">
Userscripts
</span>
</a>
<label class="md-nav__link " for="__nav_6_4" id="__nav_6_4_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_6_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6_4">
<span class="md-nav__icon md-icon"></span>
Userscripts
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../userscripts/list/" class="md-nav__link">
<span class="md-ellipsis">
Browse userscripts
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6_5">
<div class="md-nav__link md-nav__container">
<a href="../../../scripts/" class="md-nav__link ">
<span class="md-ellipsis">
Scripts
</span>
</a>
<label class="md-nav__link " for="__nav_6_5" id="__nav_6_5_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_6_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6_5">
<span class="md-nav__icon md-icon"></span>
Scripts
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../scripts/list/" class="md-nav__link">
<span class="md-ellipsis">
Browse scripts
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6_6">
<div class="md-nav__link md-nav__container">
<a href="../../../utilities/" class="md-nav__link ">
<span class="md-ellipsis">
Utilities
</span>
</a>
<label class="md-nav__link " for="__nav_6_6" id="__nav_6_6_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_6_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6_6">
<span class="md-nav__icon md-icon"></span>
Utilities
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../utilities/list/" class="md-nav__link">
<span class="md-ellipsis">
Browse utilities
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6_7">
<div class="md-nav__link md-nav__container">
<a href="../../../integrations/" class="md-nav__link ">
<span class="md-ellipsis">
Integrations
</span>
</a>
<label class="md-nav__link " for="__nav_6_7" id="__nav_6_7_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_6_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6_7">
<span class="md-nav__icon md-icon"></span>
Integrations
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../integrations/list/" class="md-nav__link">
<span class="md-ellipsis">
Browse integrations
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../../../api/" class="md-nav__link">
<span class="md-ellipsis">
API
</span>
</a>
</li>
<li class="md-nav__item">
<a href="https://discourse.stashapp.cc" class="md-nav__link">
<span class="md-ellipsis">
Community forum
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../code-of-conduct/" class="md-nav__link">
<span class="md-ellipsis">
Code of conduct
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#xpath-scraper-templates" class="md-nav__link">
<span class="md-ellipsis">
XPath scraper templates
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scraper-configuration-file-format" class="md-nav__link">
<span class="md-ellipsis">
Scraper configuration file format
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#actions" class="md-nav__link">
<span class="md-ellipsis">
Actions
</span>
</a>
<nav class="md-nav" aria-label="Actions">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#script" class="md-nav__link">
<span class="md-ellipsis">
Script
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scrapexpath" class="md-nav__link">
<span class="md-ellipsis">
scrapeXPath
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scrapejson" class="md-nav__link">
<span class="md-ellipsis">
scrapeJson
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scrapexpath-and-scrapejson-use-with-performerbyname" class="md-nav__link">
<span class="md-ellipsis">
scrapeXPath and scrapeJson use with performerByName
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scrapexpath-and-scrapejson-use-with-scenebyfragment-and-scenebyqueryfragment" class="md-nav__link">
<span class="md-ellipsis">
scrapeXPath and scrapeJson use with sceneByFragment and sceneByQueryFragment
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scrapexpath-and-scrapejson-use-with-sceneperformergallerygroupbyurl" class="md-nav__link">
<span class="md-ellipsis">
scrapeXPath and scrapeJson use with &lt;scene|performer|gallery|group&gt;ByURL
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#stash" class="md-nav__link">
<span class="md-ellipsis">
Stash
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#xpath-and-json-scrapers-configuration" class="md-nav__link">
<span class="md-ellipsis">
Xpath and JSON scrapers configuration
</span>
</a>
<nav class="md-nav" aria-label="Xpath and JSON scrapers configuration">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#fixed-attribute-values" class="md-nav__link">
<span class="md-ellipsis">
Fixed attribute values
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#common-fragments" class="md-nav__link">
<span class="md-ellipsis">
Common fragments
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#post-processing-options" class="md-nav__link">
<span class="md-ellipsis">
Post-processing options
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#xpath-resources" class="md-nav__link">
<span class="md-ellipsis">
XPath resources:
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#gjson-resources" class="md-nav__link">
<span class="md-ellipsis">
GJSON resources:
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#debugging-support" class="md-nav__link">
<span class="md-ellipsis">
Debugging support
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#cdp-support" class="md-nav__link">
<span class="md-ellipsis">
CDP support
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#cdp-click-support" class="md-nav__link">
<span class="md-ellipsis">
CDP Click support
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#cookie-support" class="md-nav__link">
<span class="md-ellipsis">
Cookie support
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#headers" class="md-nav__link">
<span class="md-ellipsis">
Headers
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#xpath-scraper-example" class="md-nav__link">
<span class="md-ellipsis">
XPath scraper example
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#json-scraper-example" class="md-nav__link">
<span class="md-ellipsis">
JSON scraper example
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#object-fields" class="md-nav__link">
<span class="md-ellipsis">
Object fields
</span>
</a>
<nav class="md-nav" aria-label="Object fields">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#gallery" class="md-nav__link">
<span class="md-ellipsis">
Gallery
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#group" class="md-nav__link">
<span class="md-ellipsis">
Group
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#image" class="md-nav__link">
<span class="md-ellipsis">
Image
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#performer" class="md-nav__link">
<span class="md-ellipsis">
Performer
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#scene" class="md-nav__link">
<span class="md-ellipsis">
Scene
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#studio" class="md-nav__link">
<span class="md-ellipsis">
Studio
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#tag" class="md-nav__link">
<span class="md-ellipsis">
Tag
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/stashapp/Stash-Docs/edit/main/docs/in-app-manual/scraping/scraperdevelopment.md" title="Edit this page" class="md-content__button md-icon" rel="edit">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10 20H6V4h7v5h5v3.1l2-2V8l-6-6H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h4zm10.2-7c.1 0 .3.1.4.2l1.3 1.3c.2.2.2.6 0 .8l-1 1-2.1-2.1 1-1c.1-.1.2-.2.4-.2m0 3.9L14.1 23H12v-2.1l6.1-6.1z"></path></svg>
</a>
<a href="https://github.com/stashapp/Stash-Docs/raw/main/docs/in-app-manual/scraping/scraperdevelopment.md" title="View source of this page" class="md-content__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 18c.56 0 1 .44 1 1s-.44 1-1 1-1-.44-1-1 .44-1 1-1m0-3c-2.73 0-5.06 1.66-6 4 .94 2.34 3.27 4 6 4s5.06-1.66 6-4c-.94-2.34-3.27-4-6-4m0 6.5a2.5 2.5 0 0 1-2.5-2.5 2.5 2.5 0 0 1 2.5-2.5 2.5 2.5 0 0 1 2.5 2.5 2.5 2.5 0 0 1-2.5 2.5M9.27 20H6V4h7v5h5v4.07c.7.08 1.36.25 2 .49V8l-6-6H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h4.5a8.2 8.2 0 0 1-1.23-2"></path></svg>
</a>
<h1 id="contributing-scrapers">Contributing Scrapers<a class="headerlink" href="#contributing-scrapers" title="Permanent link"></a></h1>
<p>Scrapers can be contributed to the community by creating a PR in <a href="https://github.com/stashapp/CommunityScrapers/pulls">this repository</a>.</p>
<h2 id="xpath-scraper-templates">XPath scraper templates<a class="headerlink" href="#xpath-scraper-templates" title="Permanent link"></a></h2>
<p>The most basic XPath scraper templates are available on <a href="https://github.com/stashapp/CommunityScrapers/tree/master/templates">CommunityScrapers repository</a>.</p>
<h2 id="scraper-configuration-file-format">Scraper configuration file format<a class="headerlink" href="#scraper-configuration-file-format" title="Permanent link"></a></h2>
<div class="highlight"><pre><span></span><code><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;site&gt;</span>
<span class="nt">performerByName</span><span class="p">:</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;single scraper config&gt;</span>
<span class="nt">performerByFragment</span><span class="p">:</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;single scraper config&gt;</span>
<span class="nt">performerByURL</span><span class="p">:</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;multiple scraper URL configs&gt;</span>
<span class="nt">sceneByName</span><span class="p">:</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;single scraper config&gt;</span>
<span class="nt">sceneByQueryFragment</span><span class="p">:</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;single scraper config&gt;</span>
<span class="nt">sceneByFragment</span><span class="p">:</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;single scraper config&gt;</span>
<span class="nt">sceneByURL</span><span class="p">:</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;multiple scraper URL configs&gt;</span>
<span class="nt">groupByURL</span><span class="p">:</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;multiple scraper URL configs&gt;</span>
<span class="nt">galleryByFragment</span><span class="p">:</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;single scraper config&gt;</span>
<span class="nt">galleryByURL</span><span class="p">:</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;multiple scraper URL configs&gt;</span>
<span class="nt">imageByFragment</span><span class="p">:</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;single scraper config&gt;</span>
<span class="nt">imageByURL</span><span class="p">:</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;multiple scraper URL configs&gt;</span>
<span class="l l-Scalar l-Scalar-Plain">&lt;other configurations&gt;</span>
</code></pre></div>
<p><code>name</code> is mandatory, all other top-level fields are optional. The inclusion of each top-level field determines what capabilities the scraper has.</p>
<p>A scraper configuration in any of the top-level fields must at least have an <code>action</code> field. The other fields are required based on the value of the <code>action</code> field.</p>
<p>The scraping types and their required fields are outlined in the following table:</p>
<table>
<thead>
<tr>
<th>Behavior</th>
<th>Required configuration</th>
</tr>
</thead>
<tbody>
<tr>
<td>Scraper in <code>Scrape...</code> dropdown button in Performer Edit page</td>
<td>Valid <code>performerByName</code> and <code>performerByFragment</code> configurations.</td>
</tr>
<tr>
<td>Scrape performer from URL</td>
<td>Valid <code>performerByURL</code> configuration with matching URL.</td>
</tr>
<tr>
<td>Scraper in query dropdown button in Scene Edit page</td>
<td>Valid <code>sceneByName</code> and <code>sceneByQueryFragment</code> configurations.</td>
</tr>
<tr>
<td>Scraper in <code>Scrape...</code> dropdown button in Scene Edit page</td>
<td>Valid <code>sceneByFragment</code> configuration.</td>
</tr>
<tr>
<td>Scrape scene from URL</td>
<td>Valid <code>sceneByURL</code> configuration with matching URL.</td>
</tr>
<tr>
<td>Scrape group from URL</td>
<td>Valid <code>groupByURL</code> configuration with matching URL. <strong>Note:</strong> <code>movieByURL</code> is also supported but is deprecated.</td>
</tr>
<tr>
<td>Scraper in <code>Scrape...</code> dropdown button in Gallery Edit page</td>
<td>Valid <code>galleryByFragment</code> configuration.</td>
</tr>
<tr>
<td>Scrape gallery from URL</td>
<td>Valid <code>galleryByURL</code> configuration with matching URL.</td>
</tr>
</tbody>
</table>
<p>URL-based scraping accepts multiple scrape configurations, and each configuration requires a <code>url</code> field. stash iterates through these configurations, attempting to match the entered URL against the <code>url</code> fields in the configuration. It executes the first scraping configuration where the entered URL contains the value of the <code>url</code> field. </p>
<h2 id="actions">Actions<a class="headerlink" href="#actions" title="Permanent link"></a></h2>
<h3 id="script">Script<a class="headerlink" href="#script" title="Permanent link"></a></h3>
<p>Executes a script to perform the scrape. The <code>script</code> field is required for this action and accepts a list of string arguments. For example:</p>
<div class="highlight"><pre><span></span><code><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">script</span>
<span class="nt">script</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">python</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">iafdScrape.py</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">query</span>
</code></pre></div>
<p>If the script specifies the python executable, Stash will find the correct python executable for your system, either <code>python</code> or <code>python3</code>. So for example. this configuration could execute <code>python iafdScrape.py query</code> or <code>python3 iafdScrape.py query</code>.
<code>python3</code> will be looked for first and if it's not found, we'll check for <code>python</code>. In the case neither are found, you will get an error.</p>
<p>Stash sends data to the script process's <code>stdin</code> stream and expects the output to be streamed to the <code>stdout</code> stream. Any errors and progress messages should be output to <code>stderr</code>.</p>
<p>The script is sent input and expects output based on the scraping type, as detailed in the following table:</p>
<table>
<thead>
<tr>
<th>Scrape type</th>
<th>Input</th>
<th>Output</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>performerByName</code></td>
<td><code>{"name": "&lt;performer query string&gt;"}</code></td>
<td>Array of JSON-encoded performer fragments (including at least <code>name</code>)</td>
</tr>
<tr>
<td><code>performerByFragment</code></td>
<td>JSON-encoded performer fragment</td>
<td>JSON-encoded performer fragment</td>
</tr>
<tr>
<td><code>performerByURL</code></td>
<td><code>{"url": "&lt;url&gt;"}</code></td>
<td>JSON-encoded performer fragment</td>
</tr>
<tr>
<td><code>sceneByName</code></td>
<td><code>{"name": "&lt;scene query string&gt;"}</code></td>
<td>Array of JSON-encoded scene fragments</td>
</tr>
<tr>
<td><code>sceneByQueryFragment</code>, <code>sceneByFragment</code></td>
<td>JSON-encoded scene fragment</td>
<td>JSON-encoded scene fragment</td>
</tr>
<tr>
<td><code>sceneByURL</code></td>
<td><code>{"url": "&lt;url&gt;"}</code></td>
<td>JSON-encoded scene fragment</td>
</tr>
<tr>
<td><code>groupByURL</code></td>
<td><code>{"url": "&lt;url&gt;"}</code></td>
<td>JSON-encoded group fragment</td>
</tr>
<tr>
<td><code>galleryByFragment</code></td>
<td>JSON-encoded gallery fragment</td>
<td>JSON-encoded gallery fragment</td>
</tr>
<tr>
<td><code>galleryByURL</code></td>
<td><code>{"url": "&lt;url&gt;"}</code></td>
<td>JSON-encoded gallery fragment</td>
</tr>
<tr>
<td><code>imageByFragment</code></td>
<td>JSON-encoded image fragment</td>
<td>JSON-encoded image fragment</td>
</tr>
<tr>
<td><code>imageByURL</code></td>
<td><code>{"url": "&lt;url&gt;"}</code></td>
<td>JSON-encoded image fragment</td>
</tr>
</tbody>
</table>
<p>For <code>performerByName</code>, only <code>name</code> is required in the returned performer fragments. One entire object is sent back to <code>performerByFragment</code> to scrape a specific performer, so the other fields may be included to assist in scraping a performer. For example, the <code>url</code> field may be filled in for the specific performer page, then <code>performerByFragment</code> can extract by using its value.</p>
<p>Python example of a performer Scraper:</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">json</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">string</span>
<span class="k">def</span><span class="w"> </span><span class="nf">readJSONInput</span><span class="p">():</span>
<span class="nb">input</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<span class="k">return</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="nb">input</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">searchPerformer</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
<span class="c1"># perform scraping here - using name for the query</span>
<span class="c1"># fill in the output</span>
<span class="n">ret</span> <span class="o">=</span> <span class="p">[]</span>
<span class="c1"># example shown for a single found performer </span>
<span class="n">p</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">p</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"some name"</span>
<span class="n">p</span><span class="p">[</span><span class="s1">'url'</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"performer url"</span>
<span class="n">ret</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="k">return</span> <span class="n">ret</span>
<span class="k">def</span><span class="w"> </span><span class="nf">scrapePerformer</span><span class="p">(</span><span class="nb">input</span><span class="p">):</span>
<span class="n">ret</span> <span class="o">=</span> <span class="p">[]</span>
<span class="c1"># get the url from the input</span>
<span class="n">url</span> <span class="o">=</span> <span class="nb">input</span><span class="p">[</span><span class="s1">'url'</span><span class="p">]</span>
<span class="k">return</span> <span class="n">scrapePerformerURL</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">debugPrint</span><span class="p">(</span><span class="n">t</span><span class="p">):</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">t</span> <span class="o">+</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">scrapePerformerURL</span><span class="p">(</span><span class="n">url</span><span class="p">):</span>
<span class="n">debugPrint</span><span class="p">(</span><span class="s2">"Reading url..."</span><span class="p">)</span>
<span class="n">debugPrint</span><span class="p">(</span><span class="s2">"Parsing html..."</span><span class="p">)</span>
<span class="c1"># parse html</span>
<span class="c1"># fill in performer details - single object</span>
<span class="n">ret</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">ret</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"fred"</span>
<span class="n">ret</span><span class="p">[</span><span class="s1">'aliases'</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"freddy"</span>
<span class="n">ret</span><span class="p">[</span><span class="s1">'ethnicity'</span><span class="p">]</span> <span class="o">=</span> <span class="s2">""</span>
<span class="c1"># and so on</span>
<span class="k">return</span> <span class="n">ret</span>
<span class="c1"># read the input </span>
<span class="n">i</span> <span class="o">=</span> <span class="n">readJSONInput</span><span class="p">()</span>
<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"query"</span><span class="p">:</span>
<span class="n">ret</span> <span class="o">=</span> <span class="n">searchPerformer</span><span class="p">(</span><span class="n">i</span><span class="p">[</span><span class="s1">'name'</span><span class="p">])</span>
<span class="nb">print</span><span class="p">(</span><span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">ret</span><span class="p">))</span>
<span class="k">elif</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"scrape"</span><span class="p">:</span>
<span class="n">ret</span> <span class="o">=</span> <span class="n">scrapePerformer</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">ret</span><span class="p">))</span>
<span class="k">elif</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"scrapeURL"</span><span class="p">:</span>
<span class="n">ret</span> <span class="o">=</span> <span class="n">scrapePerformerURL</span><span class="p">(</span><span class="n">i</span><span class="p">[</span><span class="s1">'url'</span><span class="p">])</span>
<span class="nb">print</span><span class="p">(</span><span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">ret</span><span class="p">))</span>
</code></pre></div>
<h3 id="scrapexpath">scrapeXPath<a class="headerlink" href="#scrapexpath" title="Permanent link"></a></h3>
<p>This action scrapes a web page using an xpath configuration to parse. This action is <strong>not valid</strong> for <code>performerByFragment</code>.</p>
<p>This action requires that the top-level <code>xPathScrapers</code> configuration is populated. The <code>scraper</code> field is required and must match the name of a scraper name configured in <code>xPathScrapers</code>. For example:</p>
<div class="highlight"><pre><span></span><code><span class="nt">sceneByURL</span><span class="p">:</span>
<span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">scrapeXPath</span>
<span class="w"> </span><span class="nt">url</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pornhub.com/view_video.php</span>
<span class="w"> </span><span class="nt">scraper</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">sceneScraper</span>
</code></pre></div>
<p>The above configuration requires that <code>sceneScraper</code> exists in the <code>xPathScrapers</code> configuration.</p>
<p>XPath scraping configurations specify the mapping between object fields and an xpath selector. The xpath scraper scrapes the applicable URL and uses xpath to populate the object fields.</p>
<h3 id="scrapejson">scrapeJson<a class="headerlink" href="#scrapejson" title="Permanent link"></a></h3>
<p>This action works in the same way as <code>scrapeXPath</code>, but uses a mapped json configuration to parse. It uses the top-level <code>jsonScrapers</code> configuration. This action is <strong>not valid</strong> for <code>performerByFragment</code>.</p>
<p>JSON scraping configurations specify the mapping between object fields and a GJSON selector. The JSON scraper scrapes the applicable URL and uses <a href="https://github.com/tidwall/gjson/blob/master/SYNTAX.md">GJSON</a> to parse the returned JSON object and populate the object fields.</p>
<h3 id="scrapexpath-and-scrapejson-use-with-performerbyname">scrapeXPath and scrapeJson use with <code>performerByName</code><a class="headerlink" href="#scrapexpath-and-scrapejson-use-with-performerbyname" title="Permanent link"></a></h3>
<p>For <code>performerByName</code>, the <code>queryURL</code> field must be present also. This field is used to perform a search query URL for performer names. The placeholder string sequence <code>{}</code> is replaced with the performer name search string. For the subsequent performer scrape to work, the <code>URL</code> field must be filled in with the URL of the performer page that matches a URL given in a <code>performerByURL</code> scraping configuration. For example:</p>
<div class="highlight"><pre><span></span><code><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Boobpedia</span>
<span class="nt">performerByName</span><span class="p">:</span>
<span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">scrapeXPath</span>
<span class="w"> </span><span class="nt">queryURL</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">http://www.boobpedia.com/wiki/index.php?title=Special%3ASearch&amp;search={}&amp;fulltext=Search</span>
<span class="w"> </span><span class="nt">scraper</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">performerSearch</span>
<span class="nt">performerByURL</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">scrapeXPath</span>
<span class="w"> </span><span class="nt">url</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">boobpedia.com/boobs/</span>
<span class="w"> </span><span class="nt">scraper</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">performerScraper</span>
<span class="nt">xPathScrapers</span><span class="p">:</span>
<span class="w"> </span><span class="nt">performerSearch</span><span class="p">:</span>
<span class="w"> </span><span class="nt">performer</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="c1"># name element</span>
<span class="w"> </span><span class="nt">URL</span><span class="p">:</span><span class="w"> </span><span class="c1"># URL element that matches the boobpedia.com/boobs/ URL above</span>
<span class="w"> </span><span class="nt">performerScraper</span><span class="p">:</span>
<span class="w"> </span><span class="c1"># ... performer scraper details ...</span>
</code></pre></div>
<h3 id="scrapexpath-and-scrapejson-use-with-scenebyfragment-and-scenebyqueryfragment">scrapeXPath and scrapeJson use with <code>sceneByFragment</code> and <code>sceneByQueryFragment</code><a class="headerlink" href="#scrapexpath-and-scrapejson-use-with-scenebyfragment-and-scenebyqueryfragment" title="Permanent link"></a></h3>
<p>For <code>sceneByFragment</code> and <code>sceneByQueryFragment</code>, the <code>queryURL</code> field must also be present. This field is used to build a query URL for scenes. For <code>sceneByFragment</code>, the <code>queryURL</code> field supports the following placeholder fields:</p>
<ul>
<li><code>{checksum}</code> - the MD5 checksum of the scene</li>
<li><code>{oshash}</code> - the oshash of the scene</li>
<li><code>{filename}</code> - the base filename of the scene</li>
<li><code>{title}</code> - the title of the scene</li>
<li><code>{url}</code> - the url of the scene</li>
</ul>
<p>These placeholder field values may be manipulated with regex replacements by adding a <code>queryURLReplace</code> section, containing a map of placeholder field to regex configuration which uses the same format as the <code>replace</code> post-process action covered below.</p>
<p>For example:</p>
<div class="highlight"><pre><span></span><code><span class="nt">sceneByFragment</span><span class="p">:</span>
<span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">scrapeJson</span>
<span class="w"> </span><span class="nt">scraper</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">sceneQueryScraper</span>
<span class="w"> </span><span class="nt">queryURL</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">https://metadataapi.net/api/scenes?parse={filename}&amp;limit=1</span>
<span class="w"> </span><span class="nt">queryURLReplace</span><span class="p">:</span>
<span class="w"> </span><span class="nt">filename</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">regex</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;some regex&gt;</span>
<span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;replacement&gt;</span>
</code></pre></div>
<p>The above configuration would scrape from the value of <code>queryURL</code>, replacing <code>{filename}</code> with the base filename of the scene, after it has been manipulated by the regex replacements.</p>
<h3 id="scrapexpath-and-scrapejson-use-with-sceneperformergallerygroupbyurl">scrapeXPath and scrapeJson use with <code>&lt;scene|performer|gallery|group&gt;ByURL</code><a class="headerlink" href="#scrapexpath-and-scrapejson-use-with-sceneperformergallerygroupbyurl" title="Permanent link"></a></h3>
<p>For <code>sceneByURL</code>, <code>performerByURL</code>, <code>galleryByURL</code> the <code>queryURL</code> can also be present if we want to use <code>queryURLReplace</code>. The functionality is the same as <code>sceneByFragment</code>, the only placeholder field available though is the <code>url</code>:</p>
<ul>
<li><code>{url}</code> - the url of the scene/performer/gallery</li>
</ul>
<div class="highlight"><pre><span></span><code><span class="nt">sceneByURL</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">scrapeJson</span>
<span class="w"> </span><span class="nt">url</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">metartnetwork.com</span>
<span class="w"> </span><span class="nt">scraper</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">sceneScraper</span>
<span class="w"> </span><span class="nt">queryURL</span><span class="p">:</span><span class="w"> </span><span class="s">"{url}"</span>
<span class="w"> </span><span class="nt">queryURLReplace</span><span class="p">:</span>
<span class="w"> </span><span class="nt">url</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">regex</span><span class="p">:</span><span class="w"> </span><span class="s">'^(?:.+\.)?([^.]+)\.com/.+movie/(\d+)/(\w+)/?$'</span>
<span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">https://www.$1.com/api/movie?name=$3&amp;date=$2</span>
</code></pre></div>
<h3 id="stash">Stash<a class="headerlink" href="#stash" title="Permanent link"></a></h3>
<p>A different stash server can be configured as a scraping source. This action applies only to <code>performerByName</code>, <code>performerByFragment</code>, <code>sceneByName</code>, <code>sceneByQueryFragment</code> and <code>sceneByFragment</code>, types. This action requires that the top-level <code>stashServer</code> field is configured.</p>
<ul>
<li><code>stashServer</code> contains a single <code>url</code> field for the remote stash server. </li>
<li>The username and password can be embedded in this string using <code>username:password@host</code>. </li>
<li>Alternatively, the <code>apiKey</code> field can be used to authenticate with the remote stash server.</li>
</ul>
<p>An example stash scrape configuration is below:</p>
<div class="highlight"><pre><span></span><code><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">stash</span>
<span class="nt">performerByName</span><span class="p">:</span>
<span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">stash</span>
<span class="nt">performerByFragment</span><span class="p">:</span>
<span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">stash</span>
<span class="nt">sceneByFragment</span><span class="p">:</span>
<span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">stash</span>
<span class="nt">sceneByName</span><span class="p">:</span>
<span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">stash</span>
<span class="nt">sceneByQueryFragment</span><span class="p">:</span>
<span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">stash</span>
<span class="nt">stashServer</span><span class="p">:</span>
<span class="w"> </span><span class="nt">apiKey</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">&lt;api key&gt;</span>
<span class="w"> </span><span class="nt">url</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">http://stashserver.com:9999</span>
</code></pre></div>
<h2 id="xpath-and-json-scrapers-configuration">Xpath and JSON scrapers configuration<a class="headerlink" href="#xpath-and-json-scrapers-configuration" title="Permanent link"></a></h2>
<p>The top-level <code>xPathScrapers</code> field contains xpath scraping configurations, freely named. These are referenced in the <code>scraper</code> field for <code>scrapeXPath</code> scrapers. </p>
<p>Likewise, the top-level <code>jsonScrapers</code> field contains json scraping configurations.</p>
<p>Collectively, these configurations are known as mapped scraping configurations. </p>
<p>A mapped scraping configuration may contain a <code>common</code> field, and must contain <code>performer</code>, <code>scene</code>, <code>group</code> or <code>gallery</code> depending on the scraping type it is configured for. </p>
<p>Within the <code>performer</code>/<code>scene</code>/<code>group</code>/<code>gallery</code> field are key/value pairs corresponding to the <a href="/help/ScraperDevelopment.md#object-fields">golang fields</a> on the performer/scene object. These fields are case-sensitive. </p>
<p>The values of these may be either a simple selector value, which tells the system where to get the value of the field from, or a more advanced configuration (see below). For example, for an xpath configuration:</p>
<div class="highlight"><pre><span></span><code><span class="nt">performer</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//h1[@itemprop="name"]</span>
</code></pre></div>
<p>This will set the <code>Name</code> attribute of the returned performer to the text content of the element that matches <code>&lt;h1 itemprop="name"&gt;...</code>.</p>
<p>For a json configuration:</p>
<div class="highlight"><pre><span></span><code><span class="nt">performer</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.name</span>
</code></pre></div>
<p>The value may also be a sub-object. If it is a sub-object, then the selector must be set to the <code>selector</code> key of the sub-object. For example, using the same xpath as above:</p>
<div class="highlight"><pre><span></span><code><span class="nt">performer</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//h1[@itemprop="name"]</span>
<span class="w"> </span><span class="nt">postProcess</span><span class="p">:</span>
<span class="w"> </span><span class="c1"># post-processing config values</span>
</code></pre></div>
<h3 id="fixed-attribute-values">Fixed attribute values<a class="headerlink" href="#fixed-attribute-values" title="Permanent link"></a></h3>
<p>Alternatively, an attribute value may be set to a fixed value, rather than scraping it from the webpage. This can be done by replacing <code>selector</code> with <code>fixed</code>. For example:</p>
<div class="highlight"><pre><span></span><code><span class="nt">performer</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Gender</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="nt">fixed</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Female</span>
</code></pre></div>
<h3 id="common-fragments">Common fragments<a class="headerlink" href="#common-fragments" title="Permanent link"></a></h3>
<p>The <code>common</code> field is used to configure selector fragments that can be referenced in the selector strings. These are key-value pairs where the key is the string to reference the fragment, and the value is the string that the fragment will be replaced with. For example:</p>
<div class="highlight"><pre><span></span><code><span class="nt">common</span><span class="p">:</span>
<span class="w"> </span><span class="nt">$infoPiece</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//div[@class="infoPiece"]/span</span>
<span class="nt">performer</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Measurements</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$infoPiece[text() = 'Measurements:']/../span[@class="smallInfo"]</span>
</code></pre></div>
<p>The <code>Measurements</code> xpath string will replace <code>$infoPiece</code> with <code>//div[@class="infoPiece"]/span</code>, resulting in: <code>//div[@class="infoPiece"]/span[text() = 'Measurements:']/../span[@class="smallInfo"]</code>.</p>
<blockquote>
<p><strong>⚠️ Note:</strong> Recursive common fragments are <strong>not</strong> supported.<br>
Referencing a common fragment within another common fragment will cause an error. For example:
</p><div class="highlight"><pre><span></span><code><span class="nt">common</span><span class="p">:</span>
<span class="w"> </span><span class="nt">$info</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//div[@class="info"]</span>
<span class="w"> </span><span class="c1"># Referencing $info in $models will cause an error</span>
<span class="w"> </span><span class="nt">$models</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$info/a[@class="model"]</span>
<span class="nt">scene</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Title</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$info/h1</span>
<span class="w"> </span><span class="nt">Performers</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$models</span>
<span class="w"> </span><span class="nt">URL</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$models/@href</span>
</code></pre></div><p></p>
</blockquote>
<h3 id="post-processing-options">Post-processing options<a class="headerlink" href="#post-processing-options" title="Permanent link"></a></h3>
<p>Post-processing operations are contained in the <code>postProcess</code> key. Post-processing operations are performed in the order they are specified. The following post-processing operations are available:</p>
<ul>
<li><code>javascript</code>: accepts a javascript code block, that must return a string value. The input string is declared in the <code>value</code> variable. If an error occurs while compiling or running the script, then the original value is returned.
Example:
<div class="highlight"><pre><span></span><code><span class="nt">performer</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//div[@class="example element"]</span>
<span class="w"> </span><span class="nt">postProcess</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">javascript</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span>
<span class="w"> </span><span class="no">// capitalise the first letter</span>
<span class="w"> </span><span class="no">if (value &amp;&amp; value.length) {</span>
<span class="w"> </span><span class="no">return value[0].toUpperCase() + value.substring(1)</span>
<span class="w"> </span><span class="no">}</span>
</code></pre></div></li>
</ul>
<p>We use <a href="https://github.com/dop251/goja"><code>goja</code> javascript engine</a> which is missing a few built-in methods and may not be consistent with other modern javascript implementations.</p>
<ul>
<li><code>feetToCm</code>: converts a string containing feet and inches numbers into centimeters. Looks for up to two separate integers and interprets the first as the number of feet, and the second as the number of inches. The numbers can be separated by any non-numeric character including the <code>.</code> character. It does not handle decimal numbers. For example <code>6.3</code> and <code>6ft3.3</code> would both be interpreted as 6 feet, 3 inches before converting into centimeters.</li>
<li><code>lbToKg</code>: converts a string containing lbs to kg.</li>
<li>
<p><code>map</code>: contains a map of input values to output values. Where a value matches one of the input values, it is replaced with the matching output value. If no value is matched, then value is unmodified.
Example:
</p><div class="highlight"><pre><span></span><code><span class="nt">performer</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Gender</span><span class="p">:</span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//div[@class="example element"]</span>
<span class="w"> </span><span class="nt">postProcess</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">map</span><span class="p">:</span>
<span class="w"> </span><span class="nt">F</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Female</span>
<span class="w"> </span><span class="nt">M</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Male</span>
<span class="w"> </span><span class="nt">Height</span><span class="p">:</span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//span[@id="height"]</span>
<span class="w"> </span><span class="nt">postProcess</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">feetToCm</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
<span class="w"> </span><span class="nt">Weight</span><span class="p">:</span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//span[@id="weight"]</span>
<span class="w"> </span><span class="nt">postProcess</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">lbToKg</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
</code></pre></div>
Gets the contents of the selected div element, and sets the returned value to:<p></p>
<ul>
<li><code>Female</code> if the scraped value is <code>F</code>;</li>
<li><code>Male</code> if the scraped value is <code>M</code>.</li>
</ul>
<p>Height and weight are extracted from the selected spans and converted to <code>cm</code> and <code>kg</code>.</p>
</li>
<li>
<p><code>parseDate</code>: if present, the value is the date format using go's reference date (2006-01-02). For example, if an example date was <code>14-Mar-2003</code>, then the date format would be <code>02-Jan-2006</code>. See the <a href="https://golang.org/pkg/time/#Parse">time.Parse documentation</a> for details. When present, the scraper will convert the input string into a date, then convert it to the string format used by stash (<code>YYYY-MM-DD</code>). Strings "Today", "Yesterday" are matched (case insensitive) and converted by the scraper so you don't need to edit/replace them.
Unix timestamps (example: 1660169451) can also be parsed by selecting <code>unix</code> as the date format.
Example:
</p><div class="highlight"><pre><span></span><code><span class="nt">Date</span><span class="p">:</span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//div[@class="value epoch"]/text()</span>
<span class="w"> </span><span class="nt">postProcess</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">parseDate</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">unix</span>
</code></pre></div><p></p>
</li>
<li>
<p><code>subtractDays</code>: if set to <code>true</code> it subtracts the value in days from the current date and returns the resulting date in stash's date format.
Example:
</p><div class="highlight"><pre><span></span><code><span class="nt">Date</span><span class="p">:</span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//strong[contains(text(),"Added:")]/following-sibling::text()</span>
<span class="w"> </span><span class="nt">postProcess</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">replace</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">regex</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">(\d+)\sdays\sago.+</span>
<span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$1</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">subtractDays</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
</code></pre></div><p></p>
</li>
<li>
<p><code>replace</code>: contains an array of sub-objects. Each sub-object must have a <code>regex</code> and <code>with</code> field. The <code>regex</code> field is the regex pattern to replace, and <code>with</code> is the string to replace it with. <code>$</code> is used to reference capture groups - <code>$1</code> is the first capture group, <code>$2</code> the second and so on. Replacements are performed in order of the array.
Example:
</p><div class="highlight"><pre><span></span><code><span class="nt">CareerLength</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$infoPiece[text() = 'Career Start and End:']/../span[@class="smallInfo"]</span>
<span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">postProcess</span><span class="p p-Indicator">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">replace</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">regex</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">\s+to\s+</span>
<span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span><span class="s">"-"</span>
</code></pre></div>
Replaces <code>2001 to 2003</code> with <code>2001-2003</code>.<p></p>
</li>
<li>
<p><code>subScraper</code>: if present, the sub-scraper will be executed after all other post-processes are complete and before parseDate. It then takes the value and performs an http request, using the value as the URL. Within the <code>subScraper</code> config is a nested scraping configuration. This allows you to traverse to other webpages to get the attribute value you are after. For more info and examples have a look at <a href="https://github.com/stashapp/stash/pull/370">#370</a>, <a href="https://github.com/stashapp/stash/pull/606">#606</a></p>
</li>
</ul>
<p>Additionally, there are a number of fixed post-processing fields that are specified at the attribute level (not in <code>postProcess</code>) that are performed after the <code>postProcess</code> operations:</p>
<ul>
<li><code>concat</code>: if an xpath matches multiple elements, and <code>concat</code> is present, then all of the elements will be concatenated together</li>
<li><code>split</code>: the inverse of <code>concat</code>. Splits a string to more elements using the separator given. For more info and examples have a look at PR <a href="https://github.com/stashapp/stash/pull/579">#579</a>
Example:
<div class="highlight"><pre><span></span><code><span class="nt">Tags</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//span[@class="list_attributes"]</span>
<span class="w"> </span><span class="nt">split</span><span class="p">:</span><span class="w"> </span><span class="s">","</span>
</code></pre></div>
Splits a comma separated list of tags located in the span and returns the tags.</li>
</ul>
<p>For backwards compatibility, <code>replace</code>, <code>subscraper</code> and <code>parseDate</code> are also allowed as keys for the attribute.</p>
<p>Post-processing on attribute post-process is done in the following order: <code>concat</code>, <code>replace</code>, <code>subscraper</code>, <code>parseDate</code> and then <code>split</code>.</p>
<h3 id="xpath-resources">XPath resources:<a class="headerlink" href="#xpath-resources" title="Permanent link"></a></h3>
<ul>
<li>Test XPaths in Firefox: https://addons.mozilla.org/en-US/firefox/addon/try-xpath/</li>
<li>XPath cheatsheet: https://devhints.io/xpath</li>
</ul>
<h3 id="gjson-resources">GJSON resources:<a class="headerlink" href="#gjson-resources" title="Permanent link"></a></h3>
<ul>
<li>GJSON Path Syntax: https://github.com/tidwall/gjson/blob/master/SYNTAX.md</li>
</ul>
<h3 id="debugging-support">Debugging support<a class="headerlink" href="#debugging-support" title="Permanent link"></a></h3>
<p>To print the received html/json from a scraper request to the log file, add the following to your scraper yml file:
</p><div class="highlight"><pre><span></span><code><span class="nt">debug</span><span class="p">:</span>
<span class="w"> </span><span class="nt">printHTML</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
</code></pre></div><p></p>
<h3 id="cdp-support">CDP support<a class="headerlink" href="#cdp-support" title="Permanent link"></a></h3>
<p>Some websites deliver content that cannot be scraped using the raw html file alone. These websites use javascript to dynamically load the content. As such, direct xpath scraping will not work on these websites. There is an option to use Chrome DevTools Protocol to load the webpage using an instance of Chrome, then scrape the result.</p>
<p>Chrome CDP support can be enabled for a specific scraping configuration by adding the following to the root of the yml configuration:
</p><div class="highlight"><pre><span></span><code><span class="nt">driver</span><span class="p">:</span>
<span class="w"> </span><span class="nt">useCDP</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
</code></pre></div><p></p>
<p>Optionally, you can add a <code>sleep</code> value under the <code>driver</code> section. This specifies the amount of time (in seconds) that the scraper should wait after loading the website to perform the scrape. This is needed as some sites need more time for loading scripts to finish. If unset, this value defaults to 2 seconds.</p>
<p>When <code>useCDP</code> is set to true, stash will execute or connect to an instance of Chrome. The behavior is dictated by the <code>Chrome CDP path</code> setting in the user configuration. If left empty, stash will attempt to find the Chrome executable in the path environment, and will fail if it cannot find one. </p>
<p><code>Chrome CDP path</code> can be set to a path to the chrome executable, or an http(s) address to remote chrome instance (for example: <code>http://localhost:9222/json/version</code>). As remote instance a docker container can also be used with the <code>chromedp/headless-shell</code> image being highly recommended.</p>
<h3 id="cdp-click-support">CDP Click support<a class="headerlink" href="#cdp-click-support" title="Permanent link"></a></h3>
<p>When using CDP you can use the <code>clicks</code> part of the <code>driver</code> section to do Mouse Clicks on elements you need to collapse or toggle. Each click element has an <code>xpath</code> value that holds the XPath for the button/element you need to click and an optional <code>sleep</code> value that is the time in seconds to wait for after clicking.
If the <code>sleep</code> value is not set it defaults to <code>2</code> seconds.</p>
<p>A demo scraper using <code>clicks</code> follows.</p>
<div class="highlight"><pre><span></span><code><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">clickDemo</span><span class="w"> </span><span class="c1"># demo only for a single URL</span>
<span class="nt">sceneByURL</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">scrapeXPath</span>
<span class="w"> </span><span class="nt">url</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">https://getbootstrap.com/docs/4.3/components/collapse/</span>
<span class="w"> </span><span class="nt">scraper</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">sceneScraper</span>
<span class="nt">xPathScrapers</span><span class="p">:</span>
<span class="w"> </span><span class="nt">sceneScraper</span><span class="p">:</span>
<span class="w"> </span><span class="nt">scene</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Title</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//head/title</span>
<span class="w"> </span><span class="nt">Details</span><span class="p">:</span><span class="w"> </span><span class="c1"># shows the id/s of the visible div/s for the Multiple targets example of the page</span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//div[@class="bd-example"]//div[@class="multi-collapse collapse show"]/@id</span>
<span class="w"> </span><span class="nt">concat</span><span class="p">:</span><span class="w"> </span><span class="s">"\n\n"</span>
<span class="nt">driver</span><span class="p">:</span>
<span class="w"> </span><span class="nt">useCDP</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
<span class="w"> </span><span class="nt">sleep</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w"> </span><span class="nt">clicks</span><span class="p">:</span><span class="w"> </span><span class="c1"># demo usage toggle on off multiple times</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">xpath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//a[@href="#multiCollapseExample1"]</span><span class="w"> </span><span class="c1"># toggle on first element</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">xpath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//button[@data-target="#multiCollapseExample2"]</span><span class="w"> </span><span class="c1"># toggle on second element</span>
<span class="w"> </span><span class="nt">sleep</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">4</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">xpath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//a[@href="#multiCollapseExample1"]</span><span class="w"> </span><span class="c1"># toggle off fist element</span>
<span class="w"> </span><span class="nt">sleep</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">xpath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//button[@data-target="#multiCollapseExample2"]</span><span class="w"> </span><span class="c1"># toggle off second element</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">xpath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//button[@data-target="#multiCollapseExample2"]</span><span class="w"> </span><span class="c1"># toggle on second element</span>
</code></pre></div>
<blockquote>
<p><strong>⚠️ Note:</strong> each <code>click</code> adds an extra delay of <code>clicks sleep</code> seconds, so the above adds <code>2+4+1+2+2=11</code> seconds to the loading time of the page.</p>
</blockquote>
<h3 id="cookie-support">Cookie support<a class="headerlink" href="#cookie-support" title="Permanent link"></a></h3>
<p>In some websites the use of cookies is needed to bypass a welcoming message or some other kind of protection. Stash supports the setting of cookies for the direct xpath scraper and the CDP based one. Due to implementation issues the usage varies a bit.</p>
<p>To use the cookie functionality a <code>cookies</code> sub section needs to be added to the <code>driver</code> section.
Each cookie element can consist of a <code>CookieURL</code> and a number of <code>Cookies</code>.</p>
<ul>
<li>
<p><code>CookieURL</code> is only needed if you are using the direct / native scraper method. It is the request url that we expect from the site we scrape. It must be in the same domain as the cookies we try to set otherwise all cookies in the same group will fail to set. If the <code>CookieURL</code> is not a valid URL then again the cookies of that group will fail.</p>
</li>
<li>
<p><code>Cookies</code> are the actual cookies we set. When using CDP that's the only part required. They have <code>Name</code>, <code>Value</code>, <code>Domain</code>, <code>Path</code> values.</p>
</li>
</ul>
<p>In the following example we use cookies for a site using the direct / native xpath scraper. We expect requests to come from <code>https://www.example.com</code> and <code>https://api.somewhere.com</code> that look for a <code>_warning</code> and a <code>_warn</code> cookie. A <code>_test2</code> cookie is also set just as a demo.</p>
<div class="highlight"><pre><span></span><code><span class="nt">driver</span><span class="p">:</span>
<span class="w"> </span><span class="nt">cookies</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">CookieURL</span><span class="p">:</span><span class="w"> </span><span class="s">"https://www.example.com"</span>
<span class="w"> </span><span class="nt">Cookies</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="s">"_warning"</span>
<span class="w"> </span><span class="nt">Domain</span><span class="p">:</span><span class="w"> </span><span class="s">".example.com"</span>
<span class="w"> </span><span class="nt">Value</span><span class="p">:</span><span class="w"> </span><span class="s">"true"</span>
<span class="w"> </span><span class="nt">Path</span><span class="p">:</span><span class="w"> </span><span class="s">"/"</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="s">"_test2"</span>
<span class="w"> </span><span class="nt">Value</span><span class="p">:</span><span class="w"> </span><span class="s">"123412"</span>
<span class="w"> </span><span class="nt">Domain</span><span class="p">:</span><span class="w"> </span><span class="s">".example.com"</span>
<span class="w"> </span><span class="nt">Path</span><span class="p">:</span><span class="w"> </span><span class="s">"/"</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">CookieURL</span><span class="p">:</span><span class="w"> </span><span class="s">"https://api.somewhere.com"</span>
<span class="w"> </span><span class="nt">Cookies</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="s">"_warn"</span>
<span class="w"> </span><span class="nt">Value</span><span class="p">:</span><span class="w"> </span><span class="s">"123"</span>
<span class="w"> </span><span class="nt">Domain</span><span class="p">:</span><span class="w"> </span><span class="s">".somewhere.com"</span>
</code></pre></div>
<p>The same functionality when using CDP would look like this:</p>
<div class="highlight"><pre><span></span><code><span class="nt">driver</span><span class="p">:</span>
<span class="w"> </span><span class="nt">useCDP</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
<span class="w"> </span><span class="nt">cookies</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">Cookies</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="s">"_warning"</span>
<span class="w"> </span><span class="nt">Domain</span><span class="p">:</span><span class="w"> </span><span class="s">".example.com"</span>
<span class="w"> </span><span class="nt">Value</span><span class="p">:</span><span class="w"> </span><span class="s">"true"</span>
<span class="w"> </span><span class="nt">Path</span><span class="p">:</span><span class="w"> </span><span class="s">"/"</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="s">"_test2"</span>
<span class="w"> </span><span class="nt">Value</span><span class="p">:</span><span class="w"> </span><span class="s">"123412"</span>
<span class="w"> </span><span class="nt">Domain</span><span class="p">:</span><span class="w"> </span><span class="s">".example.com"</span>
<span class="w"> </span><span class="nt">Path</span><span class="p">:</span><span class="w"> </span><span class="s">"/"</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">Cookies</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="s">"_warn"</span>
<span class="w"> </span><span class="nt">Value</span><span class="p">:</span><span class="w"> </span><span class="s">"123"</span>
<span class="w"> </span><span class="nt">Domain</span><span class="p">:</span><span class="w"> </span><span class="s">".somewhere.com"</span>
</code></pre></div>
<p>For some sites, the value of the cookie itself doesn't actually matter. In these cases, we can use the <code>ValueRandom</code>
property instead of <code>Value</code>. Unlike <code>Value</code>, <code>ValueRandom</code> requires an integer value greater than <code>0</code> where the value
indicates how long the cookie string should be.</p>
<p>In the following example, we will adapt the previous cookies to use <code>ValueRandom</code> instead. We set the <code>_test2</code> cookie
to randomly generate a value with a length of 6 characters and the <code>_warn</code> cookie to a length of 3.</p>
<div class="highlight"><pre><span></span><code><span class="nt">driver</span><span class="p">:</span>
<span class="w"> </span><span class="nt">cookies</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">CookieURL</span><span class="p">:</span><span class="w"> </span><span class="s">"https://www.example.com"</span>
<span class="w"> </span><span class="nt">Cookies</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="s">"_warning"</span>
<span class="w"> </span><span class="nt">Domain</span><span class="p">:</span><span class="w"> </span><span class="s">".example.com"</span>
<span class="w"> </span><span class="nt">Value</span><span class="p">:</span><span class="w"> </span><span class="s">"true"</span>
<span class="w"> </span><span class="nt">Path</span><span class="p">:</span><span class="w"> </span><span class="s">"/"</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="s">"_test2"</span>
<span class="w"> </span><span class="nt">ValueRandom</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">6</span>
<span class="w"> </span><span class="nt">Domain</span><span class="p">:</span><span class="w"> </span><span class="s">".example.com"</span>
<span class="w"> </span><span class="nt">Path</span><span class="p">:</span><span class="w"> </span><span class="s">"/"</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">CookieURL</span><span class="p">:</span><span class="w"> </span><span class="s">"https://api.somewhere.com"</span>
<span class="w"> </span><span class="nt">Cookies</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="s">"_warn"</span>
<span class="w"> </span><span class="nt">ValueRandom</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">3</span>
<span class="w"> </span><span class="nt">Domain</span><span class="p">:</span><span class="w"> </span><span class="s">".somewhere.com"</span>
</code></pre></div>
<p>When developing a scraper you can have a look at the cookies set by a site by adding</p>
<ul>
<li>
<p>a <code>CookieURL</code> if you use the direct xpath scraper</p>
</li>
<li>
<p>a <code>Domain</code> if you use the CDP scraper</p>
</li>
</ul>
<p>and having a look at the log / console in debug mode.</p>
<h3 id="headers">Headers<a class="headerlink" href="#headers" title="Permanent link"></a></h3>
<p>Sending request headers is possible when using a scraper.
Headers can be set in the <code>driver</code> section and are supported for plain, CDP enabled and JSON scrapers.
They consist of a Key and a Value. If the Key is empty or not defined then the header is ignored.</p>
<div class="highlight"><pre><span></span><code><span class="nt">driver</span><span class="p">:</span>
<span class="w"> </span><span class="nt">headers</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">Key</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">User-Agent</span>
<span class="w"> </span><span class="nt">Value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">My Stash Scraper</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">Key</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Authorization</span>
<span class="w"> </span><span class="nt">Value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Bearer ds3sdfcFdfY17p4qBkTVF03zscUU2glSjWF17bZyoe8</span>
</code></pre></div>
<ul>
<li>headers are set after stash's <code>User-Agent</code> configuration option is applied.
This means setting a <code>User-Agent</code> header from the scraper overrides the one in the configuration settings.</li>
</ul>
<h3 id="xpath-scraper-example">XPath scraper example<a class="headerlink" href="#xpath-scraper-example" title="Permanent link"></a></h3>
<p>A performer and scene xpath scraper is shown as an example below:</p>
<div class="highlight"><pre><span></span><code><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Pornhub</span>
<span class="nt">performerByURL</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">scrapeXPath</span>
<span class="w"> </span><span class="nt">url</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pornhub.com</span>
<span class="w"> </span><span class="nt">scraper</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">performerScraper</span>
<span class="nt">sceneByURL</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">scrapeXPath</span>
<span class="w"> </span><span class="nt">url</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pornhub.com/view_video.php</span>
<span class="w"> </span><span class="nt">scraper</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">sceneScraper</span>
<span class="nt">xPathScrapers</span><span class="p">:</span>
<span class="w"> </span><span class="nt">performerScraper</span><span class="p">:</span>
<span class="w"> </span><span class="nt">common</span><span class="p">:</span>
<span class="w"> </span><span class="nt">$infoPiece</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//div[@class="infoPiece"]/span</span>
<span class="w"> </span><span class="nt">performer</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//h1[@itemprop="name"]</span>
<span class="w"> </span><span class="nt">Birthdate</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//span[@itemprop="birthDate"]</span>
<span class="w"> </span><span class="nt">parseDate</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Jan 2, 2006</span>
<span class="w"> </span><span class="nt">Twitter</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//span[text() = 'Twitter']/../@href</span>
<span class="w"> </span><span class="nt">Instagram</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//span[text() = 'Instagram']/../@href</span>
<span class="w"> </span><span class="nt">Measurements</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$infoPiece[text() = 'Measurements:']/../span[@class="smallInfo"]</span>
<span class="w"> </span><span class="nt">Height</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$infoPiece[text() = 'Height:']/../span[@class="smallInfo"]</span>
<span class="w"> </span><span class="nt">postProcess</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">replace</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">regex</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">.*\((\d+) cm\)</span>
<span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$1</span>
<span class="w"> </span><span class="nt">Ethnicity</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$infoPiece[text() = 'Ethnicity:']/../span[@class="smallInfo"]</span>
<span class="w"> </span><span class="nt">FakeTits</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$infoPiece[text() = 'Fake Boobs:']/../span[@class="smallInfo"]</span>
<span class="w"> </span><span class="nt">Piercings</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$infoPiece[text() = 'Piercings:']/../span[@class="smallInfo"]</span>
<span class="w"> </span><span class="nt">Tattoos</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$infoPiece[text() = 'Tattoos:']/../span[@class="smallInfo"]</span>
<span class="w"> </span><span class="nt">CareerLength</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$infoPiece[text() = 'Career Start and End:']/../span[@class="smallInfo"]</span>
<span class="w"> </span><span class="nt">postProcess</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">replace</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">regex</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">\s+to\s+</span>
<span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span><span class="s">"-"</span>
<span class="w"> </span><span class="nt">sceneScraper</span><span class="p">:</span>
<span class="w"> </span><span class="nt">common</span><span class="p">:</span>
<span class="w"> </span><span class="nt">$performer</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//div[@class="pornstarsWrapper"]/a[@data-mxptype="Pornstar"]</span>
<span class="w"> </span><span class="nt">$studio</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//div[@data-type="channel"]/a</span>
<span class="w"> </span><span class="nt">scene</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Title</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//div[@id="main-container"]/@data-video-title</span>
<span class="w"> </span><span class="nt">Tags</span><span class="p">:</span><span class="w"> </span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">//div[@class="categoriesWrapper"]//a[not(@class="add-btn-small ")]</span>
<span class="w"> </span><span class="nt">Performers</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$performer/@data-mxptext</span>
<span class="w"> </span><span class="nt">URL</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$performer/@href</span>
<span class="w"> </span><span class="nt">Studio</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$studio</span>
<span class="w"> </span><span class="nt">URL</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$studio/@href</span><span class="w"> </span>
</code></pre></div>
<p>See also <a href="https://github.com/stashapp/stash/pull/333">#333</a> for more examples.</p>
<h3 id="json-scraper-example">JSON scraper example<a class="headerlink" href="#json-scraper-example" title="Permanent link"></a></h3>
<p>A performer and scene scraper for ThePornDB is shown below:</p>
<div class="highlight"><pre><span></span><code><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ThePornDB</span>
<span class="nt">performerByName</span><span class="p">:</span>
<span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">scrapeJson</span>
<span class="w"> </span><span class="nt">queryURL</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">https://api.metadataapi.net/performers?q={}</span>
<span class="w"> </span><span class="nt">scraper</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">performerSearch</span>
<span class="nt">performerByURL</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">scrapeJson</span>
<span class="w"> </span><span class="nt">url</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">https://api.metadataapi.net/performers/</span>
<span class="w"> </span><span class="nt">scraper</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">performerScraper</span>
<span class="nt">sceneByURL</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">scrapeJson</span>
<span class="w"> </span><span class="nt">url</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">https://api.metadataapi.net/scenes/</span>
<span class="w"> </span><span class="nt">scraper</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">sceneScraper</span>
<span class="nt">sceneByFragment</span><span class="p">:</span>
<span class="w"> </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">scrapeJson</span>
<span class="w"> </span><span class="nt">queryURL</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">https://api.metadataapi.net/scenes?parse={filename}&amp;hash={oshash}&amp;limit=1</span>
<span class="w"> </span><span class="nt">scraper</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">sceneQueryScraper</span>
<span class="w"> </span><span class="nt">queryURLReplace</span><span class="p">:</span>
<span class="w"> </span><span class="nt">filename</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">regex</span><span class="p">:</span><span class="w"> </span><span class="s">"[^a-zA-Z\\d\\-._~]"</span><span class="w"> </span><span class="c1"># clean filename so that it can construct a valid url</span>
<span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span><span class="s">"."</span><span class="w"> </span><span class="c1"># "%20"</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">regex</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">HEVC</span>
<span class="w"> </span><span class="nt">with</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">regex</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">x265</span>
<span class="w"> </span><span class="nt">with</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">regex</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">\.+</span>
<span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span><span class="s">"."</span>
<span class="nt">jsonScrapers</span><span class="p">:</span>
<span class="w"> </span><span class="nt">performerSearch</span><span class="p">:</span>
<span class="w"> </span><span class="nt">performer</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.#.name</span>
<span class="w"> </span><span class="nt">URL</span><span class="p">:</span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.#.id</span>
<span class="w"> </span><span class="nt">postProcess</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">replace</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">regex</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">^</span>
<span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">https://api.metadataapi.net/performers/</span>
<span class="w"> </span><span class="nt">performerScraper</span><span class="p">:</span>
<span class="w"> </span><span class="nt">common</span><span class="p">:</span>
<span class="w"> </span><span class="nt">$extras</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.extras</span>
<span class="w"> </span><span class="nt">performer</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.name</span>
<span class="w"> </span><span class="nt">Gender</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$extras.gender</span>
<span class="w"> </span><span class="nt">Birthdate</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$extras.birthday</span>
<span class="w"> </span><span class="nt">Ethnicity</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$extras.ethnicity</span>
<span class="w"> </span><span class="nt">Height</span><span class="p">:</span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$extras.height</span>
<span class="w"> </span><span class="nt">postProcess</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">replace</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">regex</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">cm</span>
<span class="w"> </span><span class="nt">with</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Measurements</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$extras.measurements</span>
<span class="w"> </span><span class="nt">Tattoos</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$extras.tattoos</span>
<span class="w"> </span><span class="nt">Piercings</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$extras.piercings</span>
<span class="w"> </span><span class="nt">Aliases</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.aliases</span>
<span class="w"> </span><span class="nt">Image</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.image</span>
<span class="w"> </span><span class="nt">sceneScraper</span><span class="p">:</span>
<span class="w"> </span><span class="nt">common</span><span class="p">:</span>
<span class="w"> </span><span class="nt">$performers</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.performers</span>
<span class="w"> </span><span class="nt">scene</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Title</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.title</span>
<span class="w"> </span><span class="nt">Details</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.description</span>
<span class="w"> </span><span class="nt">Date</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.date</span>
<span class="w"> </span><span class="nt">URL</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.url</span>
<span class="w"> </span><span class="nt">Image</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.background.small</span>
<span class="w"> </span><span class="nt">Performers</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.performers.#.name</span>
<span class="w"> </span><span class="nt">Studio</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.site.name</span>
<span class="w"> </span><span class="nt">Tags</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.tags.#.tag</span>
<span class="w"> </span><span class="nt">sceneQueryScraper</span><span class="p">:</span>
<span class="w"> </span><span class="nt">common</span><span class="p">:</span>
<span class="w"> </span><span class="nt">$data</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.0</span>
<span class="w"> </span><span class="nt">$performers</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">data.0.performers</span>
<span class="w"> </span><span class="nt">scene</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Title</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$data.title</span>
<span class="w"> </span><span class="nt">Details</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$data.description</span>
<span class="w"> </span><span class="nt">Date</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$data.date</span>
<span class="w"> </span><span class="nt">URL</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$data.url</span>
<span class="w"> </span><span class="nt">Image</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$data.background.small</span>
<span class="w"> </span><span class="nt">Performers</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$data.performers.#.name</span>
<span class="w"> </span><span class="nt">Studio</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$data.site.name</span>
<span class="w"> </span><span class="nt">Tags</span><span class="p">:</span>
<span class="w"> </span><span class="nt">Name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">$data.tags.#.tag</span>
<span class="nt">driver</span><span class="p">:</span>
<span class="w"> </span><span class="nt">headers</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">Key</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">User-Agent</span>
<span class="w"> </span><span class="nt">Value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Stash JSON Scraper</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">Key</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Authorization</span>
<span class="w"> </span><span class="nt">Value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Bearer lPdwFdfY17p4qBkTVF03zscUU2glSjdf17bZyoe</span><span class="w"> </span><span class="c1"># use an actual API Key here</span>
<span class="c1"># Last Updated April 7, 2021</span>
</code></pre></div>
<h2 id="object-fields">Object fields<a class="headerlink" href="#object-fields" title="Permanent link"></a></h2>
<h3 id="gallery">Gallery<a class="headerlink" href="#gallery" title="Permanent link"></a></h3>
<div class="highlight"><pre><span></span><code>Code
Date
Details
Performers (see Performer fields)
Photographer
Rating
Studio (see Studio Fields)
Tags (see Tag fields)
Title
URLs
</code></pre></div>
<blockquote>
<p><strong>Important</strong>: <code>Title</code> field is required. </p>
</blockquote>
<h3 id="group">Group<a class="headerlink" href="#group" title="Permanent link"></a></h3>
<div class="highlight"><pre><span></span><code>Aliases
BackImage
Date
Director
Duration
FrontImage
Name
Rating
Studio (see Studio Fields)
Synopsis
Tags (see Tag fields)
URLs
</code></pre></div>
<blockquote>
<p><strong>Important</strong>: <code>Name</code> field is required. </p>
</blockquote>
<h3 id="image">Image<a class="headerlink" href="#image" title="Permanent link"></a></h3>
<div class="highlight"><pre><span></span><code>Code
Date
Details
Performers (see Performer fields)
Photographer
Rating
Studio (see Studio Fields)
Tags (see Tag fields)
Title
URLs
</code></pre></div>
<h3 id="performer">Performer<a class="headerlink" href="#performer" title="Permanent link"></a></h3>
<div class="highlight"><pre><span></span><code>Aliases
Birthdate
CareerLength
Circumcised
Country
DeathDate
Details
Disambiguation
Ethnicity
EyeColor
FakeTits
Gender
HairColor
Height
Measurements
Name
PenisLength
Piercings
Tags (see Tag fields)
Tattoos
URLs
Weight
</code></pre></div>
<blockquote>
<p><strong>Important</strong>: <code>Name</code> field is required. </p>
<p><strong>Note:</strong> - <code>Gender</code> must be one of <code>male</code>, <code>female</code>, <code>transgender_male</code>, <code>transgender_female</code>, <code>intersex</code>, <code>non_binary</code> (case insensitive).</p>
</blockquote>
<h3 id="scene">Scene<a class="headerlink" href="#scene" title="Permanent link"></a></h3>
<div class="highlight"><pre><span></span><code>Code
Date
Details
Director
Groups (see Group Fields)
Image
Performers (see Performer fields)
Studio (see Studio Fields)
Tags (see Tag fields)
Title
URLs
</code></pre></div>
<blockquote>
<p><strong>Important</strong>: <code>Title</code> field is required only if fileless.</p>
</blockquote>
<h3 id="studio">Studio<a class="headerlink" href="#studio" title="Permanent link"></a></h3>
<div class="highlight"><pre><span></span><code>Name
URL
</code></pre></div>
<blockquote>
<p><strong>Important</strong>: <code>Name</code> field is required. </p>
</blockquote>
<h3 id="tag">Tag<a class="headerlink" href="#tag" title="Permanent link"></a></h3>
<div class="highlight"><pre><span></span><code>Name
</code></pre></div>
<blockquote>
<p><strong>Important</strong>: <code>Name</code> field is required. </p>
</blockquote>
<aside class="md-source-file">
<span class="md-source-file__fact">
<span class="md-icon" title="Last update">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"></path></svg>
</span>
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="November 14, 2024 11:27:50 UTC">November 14, 2024</span>
</span>
<span class="md-source-file__fact">
<span class="md-icon" title="Created">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14.47 15.08 11 13V7h1.5v5.25l3.08 1.83c-.41.28-.79.62-1.11 1m-1.39 4.84c-.36.05-.71.08-1.08.08-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8c0 .37-.03.72-.08 1.08.69.1 1.33.32 1.92.64.1-.56.16-1.13.16-1.72 0-5.5-4.5-10-10-10S2 6.5 2 12s4.47 10 10 10c.59 0 1.16-.06 1.72-.16-.32-.59-.54-1.23-.64-1.92M18 15v3h-3v2h3v3h2v-3h3v-2h-3v-3z"></path></svg>
</span>
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="November 14, 2024 11:27:50 UTC">November 14, 2024</span>
</span>
<span class="md-source-file__fact">
<span class="md-icon" title="Contributors">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34-.46-1.16-1.11-1.47-1.11-1.47-.91-.62.07-.6.07-.6 1 .07 1.53 1.03 1.53 1.03.87 1.52 2.34 1.07 2.91.83.09-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.92 0-1.11.38-2 1.03-2.71-.1-.25-.45-1.29.1-2.64 0 0 .84-.27 2.75 1.02.79-.22 1.65-.33 2.5-.33s1.71.11 2.5.33c1.91-1.29 2.75-1.02 2.75-1.02.55 1.35.2 2.39.1 2.64.65.71 1.03 1.6 1.03 2.71 0 3.82-2.34 4.66-4.57 4.91.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2"></path></svg>
</span>
<span>GitHub</span>
<nav>
<a href="https://github.com/DogmaDragon" class="md-author" title="@DogmaDragon">
<img src="https://avatars.githubusercontent.com/u/103123951?v=4&amp;size=72" alt="DogmaDragon">
</a>
<a href="https://github.com/web-flow" class="md-author" title="@web-flow">
<img src="https://avatars.githubusercontent.com/u/19864447?v=4&amp;size=72" alt="web-flow">
</a>
</nav>
</span>
</aside>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"></path></svg>
Back to top
</button>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
<div class="md-copyright__highlight">
Copyright © 2017 - 2024 stashapp contributors
</div>
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
<div class="md-social">
<a href="https://opencollective.com/stashapp" target="_blank" rel="noopener" title="opencollective.com" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12c2.54 0 4.894-.79 6.834-2.135l-3.107-3.109a7.715 7.715 0 1 1 0-13.512l3.107-3.109A11.94 11.94 0 0 0 12 0m9.865 5.166-3.109 3.107A7.7 7.7 0 0 1 19.715 12a7.7 7.7 0 0 1-.959 3.727l3.109 3.107A11.94 11.94 0 0 0 24 12c0-2.54-.79-4.894-2.135-6.834"></path></svg>
</a>
<a href="https://github.com/stashapp" target="_blank" rel="noopener" title="github.com" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"></path></svg>
</a>
<a href="https://hub.docker.com/r/stashapp/stash" target="_blank" rel="noopener" title="hub.docker.com" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13.983 11.078h2.119a.186.186 0 0 0 .186-.185V9.006a.186.186 0 0 0-.186-.186h-2.119a.185.185 0 0 0-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 0 0 .186-.186V3.574a.186.186 0 0 0-.186-.185h-2.118a.185.185 0 0 0-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 0 0 .186-.186V6.29a.186.186 0 0 0-.186-.185h-2.118a.185.185 0 0 0-.185.185v1.887c0 .102.082.185.185.186m-2.93 0h2.12a.186.186 0 0 0 .184-.186V6.29a.185.185 0 0 0-.185-.185H8.1a.185.185 0 0 0-.185.185v1.887c0 .102.083.185.185.186m-2.964 0h2.119a.186.186 0 0 0 .185-.186V6.29a.185.185 0 0 0-.185-.185H5.136a.186.186 0 0 0-.186.185v1.887c0 .102.084.185.186.186m5.893 2.715h2.118a.186.186 0 0 0 .186-.185V9.006a.186.186 0 0 0-.186-.186h-2.118a.185.185 0 0 0-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 0 0 .184-.185V9.006a.185.185 0 0 0-.184-.186h-2.12a.185.185 0 0 0-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 0 0 .185-.185V9.006a.185.185 0 0 0-.184-.186h-2.12a.186.186 0 0 0-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 0 0 .184-.185V9.006a.185.185 0 0 0-.184-.186h-2.12a.185.185 0 0 0-.184.185v1.888c0 .102.082.185.185.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51q-.508.001-1.01.087c-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.75.75 0 0 0-.75.748 11.4 11.4 0 0 0 .692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137a15.7 15.7 0 0 0 2.93-.266 12.3 12.3 0 0 0 3.823-1.389 10.5 10.5 0 0 0 2.61-2.136c1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288Z"></path></svg>
</a>
<a href="https://discord.gg/frQ7qBvB3S" target="_blank" rel="noopener" title="discord.gg" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20.317 4.37a19.8 19.8 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.3 18.3 0 0 0-5.487 0 13 13 0 0 0-.617-1.25.08.08 0 0 0-.079-.037A19.7 19.7 0 0 0 3.677 4.37a.1.1 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.08.08 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.08.08 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13 13 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10 10 0 0 0 .372-.292.07.07 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.07.07 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.3 12.3 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.08.08 0 0 0 .084.028 19.8 19.8 0 0 0 6.002-3.03.08.08 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.06.06 0 0 0-.031-.03M8.02 15.33c-1.182 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418m7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418"></path></svg>
</a>
<a href="https://discourse.stashapp.cc" target="_blank" rel="noopener" title="discourse.stashapp.cc" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12.103 0C18.666 0 24 5.485 24 11.997c0 6.51-5.33 11.99-11.9 11.99L0 24V11.79C0 5.28 5.532 0 12.103 0m.116 4.563a7.4 7.4 0 0 0-6.337 3.57 7.25 7.25 0 0 0-.148 7.22L4.4 19.61l4.794-1.074a7.42 7.42 0 0 0 8.136-1.39 7.26 7.26 0 0 0 1.737-7.997 7.375 7.375 0 0 0-6.84-4.585z"></path></svg>
</a>
<a href="https://discuss.online/c/stashapp" target="_blank" rel="noopener" title="discuss.online" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M2.96 4.223a4 4 0 0 0-.333.019A2.84 2.84 0 0 0 .474 5.628c-.475.8-.593 1.68-.35 2.497.242.816.83 1.558 1.698 2.145l.016.011c.746.45 1.492.743 2.288.9-.02.332-.028.669-.006 1.018.063 1.043.436 2 .996 2.85l-2.006.818a.42.42 0 0 0-.228.224.42.42 0 0 0 .088.455.42.42 0 0 0 .294.123.4.4 0 0 0 .16-.031l2.209-.904c.408.486.87.932 1.372 1.318q.03.02.06.043l-1.291 1.71a.416.416 0 0 0 .664.5l1.314-1.738a9.3 9.3 0 0 0 2.229 1.025c.383.72 1.138 1.187 2.02 1.187.89 0 1.644-.501 2.024-1.207a9.4 9.4 0 0 0 2.208-1.027l1.332 1.76a.416.416 0 0 0 .744-.193.42.42 0 0 0-.08-.307l-1.31-1.735c.008-.007.018-.01.026-.018.497-.38.955-.818 1.362-1.294l2.155.88a.416.416 0 0 0 .541-.228.415.415 0 0 0-.227-.544l-1.944-.792c.577-.854.97-1.819 1.05-2.87.027-.35.025-.691.009-1.026a7 7 0 0 0 2.273-.897l.017-.012c.868-.587 1.456-1.328 1.698-2.145.242-.816.125-1.697-.35-2.497a2.84 2.84 0 0 0-2.155-1.386 3 3 0 0 0-.332-.019c-.786-.015-1.623.23-2.429.694-.593.342-1.125.867-1.543 1.439-1.17-.67-2.693-1.048-4.564-1.078a16 16 0 0 0-.51 0c-2.086.034-3.755.43-5.015 1.144-.003-.003-.005-.011-.008-.015-.423-.591-.973-1.136-1.584-1.489-.805-.465-1.643-.708-2.428-.694Zm.285.736c.557.042 1.17.236 1.779.588.485.28.976.755 1.346 1.27a6 6 0 0 0-.497.408c-.92.852-1.461 1.96-1.668 3.233a6.2 6.2 0 0 1-1.984-.794C1.466 9.15 1.005 8.54.821 7.919.636 7.295.713 6.648 1.098 6c.375-.63.928-.953 1.612-1.032a3 3 0 0 1 .535-.007Zm17.51 0a3 3 0 0 1 .535.008c.684.078 1.237.402 1.612 1.032.385.648.462 1.296.277 1.92-.184.622-.645 1.231-1.4 1.744a6.2 6.2 0 0 1-1.96.789c-.194-1.297-.737-2.434-1.666-3.302a6 6 0 0 0-.47-.392c.364-.49.828-.943 1.293-1.212.61-.351 1.222-.545 1.779-.587Zm-8.749 1.045a15 15 0 0 1 .487 0c2.39.039 4.085.67 5.163 1.678 1.15 1.075 1.642 2.6 1.5 4.467-.132 1.707-1.221 3.228-2.653 4.324a9 9 0 0 1-2.225 1.229c.003-.045.014-.089.014-.135.003-1.196-.932-2.213-2.292-2.213s-2.322 1.015-2.292 2.221c.001.05.014.097.018.147a8.9 8.9 0 0 1-2.278-1.245c-1.423-1.095-2.5-2.613-2.603-4.322-.113-1.857.378-3.339 1.521-4.397s2.986-1.711 5.64-1.754m-3.642 6.829a1.096 1.096 0 1 0 0 2.192 1.096 1.096 0 0 0 0-2.192m7.282.011a1.086 1.086 0 1 0 0 2.173 1.086 1.086 0 0 0 0-2.173M12 16.084c1.024 0 1.565.638 1.563 1.482-.001.785-.672 1.485-1.563 1.485-.917 0-1.54-.562-1.563-1.493-.022-.834.54-1.474 1.563-1.474"></path></svg>
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<script id="__config" type="application/json">{"base": "../../..", "features": ["header.autohide", "announce.dismiss", "content.action.edit", "content.action.view", "search.highlight", "search.share", "navigation.instant", "navigation.instant.progress", "navigation.tabs", "navigation.sections", "toc.follow", "navigation.top", "navigation.indexes", "content.tooltips", "content.code.copy"], "search": "../../../assets/javascripts/workers/search.973d3a69.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
<script src="../../../assets/javascripts/bundle.92b07e13.min.js"></script>
<script id="init-glightbox">const lightbox = GLightbox({"touchNavigation": true, "loop": false, "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom", "slideEffect": "slide"});
document$.subscribe(()=>{ lightbox.reload(); });
</script></body></html>