[
  {
    "path": ".actor/Dockerfile",
    "content": "FROM sherlock/sherlock as sherlock\n\n# Install Node.js\nRUN apt-get update; apt-get install curl gpg -y\nRUN mkdir -p /etc/apt/keyrings\nRUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg\nRUN echo \"deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main\" | tee /etc/apt/sources.list.d/nodesource.list\nRUN apt-get update && apt-get install -y curl bash git jq jo xz-utils nodejs\n\n# Install Apify CLI (node.js) for the Actor Runtime\nRUN npm -g install apify-cli\n\n# Install Dependencies for the Actor Shell Script\nRUN apt-get update && apt-get install -y bash jq jo xz-utils nodejs\n\n# Copy Actor dir with the actorization shell script\nCOPY .actor/ .actor\n\nENTRYPOINT [\".actor/actor.sh\"]\n"
  },
  {
    "path": ".actor/README.md",
    "content": "# Sherlock Actor on Apify\n\n[![Sherlock Actor](https://apify.com/actor-badge?actor=netmilk/sherlock)](https://apify.com/netmilk/sherlock?fpr=sherlock)\n\nThis Actor wraps the [Sherlock Project](https://sherlockproject.xyz/) to provide serverless username reconnaissance across social networks in the cloud. It helps you find usernames across multiple social media platforms without installing and running the tool locally.\n\n## What are Actors?\n[Actors](https://docs.apify.com/platform/actors?fpr=sherlock) are serverless microservices running on the [Apify Platform](https://apify.com/?fpr=sherlock). They are based on the [Actor SDK](https://docs.apify.com/sdk/js?fpr=sherlock) and can be found in the [Apify Store](https://apify.com/store?fpr=sherlock). Learn more about Actors in the [Apify Whitepaper](https://whitepaper.actor?fpr=sherlock).\n\n## Usage\n\n### Apify Console\n\n1. Go to the Apify Actor page\n2. Click \"Run\"\n3. In the input form, fill in **Username(s)** to search for\n4. The Actor will run and produce its outputs in the default datastore\n\n\n### Apify CLI\n\n```bash\napify call YOUR_USERNAME/sherlock --input='{\n  \"usernames\": [\"johndoe\", \"janedoe\"]\n}'\n```\n\n### Using Apify API\n\n```bash\ncurl --request POST \\\n  --url \"https://api.apify.com/v2/acts/YOUR_USERNAME~sherlock/run\" \\\n  --header 'Content-Type: application/json' \\\n  --header 'Authorization: Bearer YOUR_API_TOKEN' \\\n  --data '{\n  \"usernames\": [\"johndoe\", \"janedoe\"],\n  }\n}'\n```\n\n## Input Parameters\n\nThe Actor accepts a JSON schema with the following structure:\n\n| Field | Type | Required | Default | Description |\n|-------|------|----------|---------|-------------|\n| `usernames` | array | Yes | - | List of usernames to search for |\n| `usernames[]` | string | Yes | \"json\" | Username to search for |\n\n\n### Example Input\n\n```json\n{\n  \"usernames\": [\"techuser\", \"designuser\"],\n}\n```\n\n## Output\n\nThe Actor provides three types of outputs:\n\n### Dataset Record*\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `username` | string | Yes | Username the search was conducted for |\n| `links` | array | Yes | Array with found links to the social media |\n| `links[]`| string | No | URL to the account\n\n### Example Dataset Item (JSON)\n\n```json\n{\n  \"username\": \"johndoe\",\n  \"links\": [\n    \"https://github.com/johndoe\" \n  ]\n}\n```\n\n## Performance & Resources\n\n- **Memory Requirements**:\n  - Minimum: 512 MB RAM\n  - Recommended: 1 GB RAM for multiple usernames\n- **Processing Time**:\n  - Single username: ~1-2 minutes\n  - Multiple usernames: 2-5 minutes\n  - Varies based on number of sites checked and response times\n\n\nFor more help, check the [Sherlock Project documentation](https://github.com/sherlock-project/sherlock) or raise an issue in the Actor's repository.\n"
  },
  {
    "path": ".actor/actor.json",
    "content": "{\n  \"actorSpecification\": 1,\n  \"name\": \"sherlock\",\n  \"version\": \"0.0\",\n  \"buildTag\": \"latest\",\n  \"environmentVariables\": {},\n  \"dockerFile\": \"./Dockerfile\", \n  \"dockerContext\": \"../\",\n  \"input\": \"./input_schema.json\",\n  \"storages\": {\n    \"dataset\": \"./dataset_schema.json\"\n  }\n}\n"
  },
  {
    "path": ".actor/actor.sh",
    "content": "#!/bin/bash\nINPUT=`apify actor:get-input | jq -r .usernames[] | xargs echo`\necho \"INPUT: $INPUT\"\n\nsherlock $INPUT\n\nfor username in $INPUT; do\n  # escape the special meaning leading characters \n  # https://github.com/jpmens/jo/blob/master/jo.md#description\n  safe_username=$(echo $username | sed 's/^@/\\\\@/' | sed 's/^:/\\\\:/' | sed 's/%/\\\\%/')\n  echo \"pushing results for username: $username, content:\"\n  cat $username.txt\n  sed '$d' $username.txt | jo -a | jo username=$safe_username links:=- | apify actor:push-data\ndone\n"
  },
  {
    "path": ".actor/dataset_schema.json",
    "content": "{\n    \"actorSpecification\": 1,\n    \"fields\":{\n      \"title\": \"Sherlock actor input\",\n      \"description\": \"This is actor input schema\",\n      \"type\": \"object\",\n      \"schemaVersion\": 1,\n      \"properties\": {\n        \"links\": {\n          \"title\": \"Links to accounts\",\n          \"type\": \"array\",\n          \"description\": \"A list of social media accounts found for the uername\"\n        },\n        \"username\": {\n          \"title\": \"Lookup username\",\n          \"type\": \"string\",\n          \"description\": \"Username the lookup was performed for\"\n        }\n      },\n      \"required\": [\n        \"username\", \n        \"links\"\n      ]\n    },\n    \"views\": {\n        \"overview\": {\n            \"title\": \"Overview\",\n            \"transformation\": {\n              \"fields\": [\n                \"username\",\n                \"links\"\n              ],\n            },\n            \"display\": {\n               \"component\": \"table\",\n               \"links\": {\n                 \"label\": \"Links\"\n               },\n               \"username\":{\n                 \"label\": \"Username\"\n               }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": ".actor/input_schema.json",
    "content": "{\n  \"title\": \"Sherlock actor input\",\n  \"description\": \"This is actor input schema\",\n  \"type\": \"object\",\n  \"schemaVersion\": 1,\n  \"properties\": {\n    \"usernames\": {\n      \"title\": \"Usernames to hunt down\",\n      \"type\": \"array\",\n      \"description\": \"A list of usernames to be checked for existence across social media\",\n      \"editor\": \"stringList\",\n      \"prefill\": [\"johndoe\"]\n    }\n  },\n  \"required\": [\n    \"usernames\"\n  ]\n}\n"
  },
  {
    "path": ".dockerignore",
    "content": ".git/\n.vscode/\nscreenshot/\ntests/\n*.txt\n!/requirements.txt\nvenv/\ndevel/"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\ncurly_bracket_next_line = false\nspaces_around_operators = true\n\n[*.{markdown,md}]\ntrim_trailing_whitespace = false\n\n[*.py]\nindent_size = 4\nquote_type = double\n"
  },
  {
    "path": ".github/CODEOWNERS",
    "content": "### REPOSITORY\n/.github/CODEOWNERS @sdushantha @ppfeister\n/.github/FUNDING.yml @sdushantha\n/LICENSE @sdushantha\n\n### PACKAGING\n# Changes made to these items without code owner approval may negatively\n# impact packaging pipelines.\n/pyproject.toml @ppfeister @sdushantha\n\n### REGRESSION\n/.github/workflows/regression.yml @ppfeister\n/tox.ini @ppfeister\n/pytest.ini @ppfeister\n/tests/ @ppfeister\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: [ sdushantha, ppfeister, matheusfelipeog ]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.yml",
    "content": "name: Bug report\ndescription: File a bug report\nlabels: [\"bug\"]\nbody:\n  - type: dropdown\n    id: package\n    attributes:\n      label: Installation method\n      description: |\n        Some packages are maintained by the community, rather than by the Sherlock Project.\n        Knowing which packages are affected helps us diagnose package-specific bugs.\n      options:\n        - Select one\n        - PyPI (via pip)\n        - Homebrew\n        - Docker\n        - Kali repository (via apt)\n        - Built from source\n        - Other (indicate below)\n    validations:\n      required: true\n  - type: input\n    id: package-version\n    attributes:\n      label: Package version\n      description: |\n        Knowing the version of the package you are using can help us diagnose your issue more quickly.\n        You can find the version by running `sherlock --version`.\n    validations:\n      required: true\n  - type: textarea\n    id: description\n    attributes:\n      label: Description\n      description: |\n        Detailed descriptions that help contributors understand and reproduce your bug are much more likely to lead to a fix.\n        Please include the following information:\n        - What you were trying to do\n        - What you expected to happen\n        - What actually happened\n      placeholder: |\n        When doing {action}, the expected result should be {expected result}.\n        When doing {action}, however, the actual result was {actual result}.\n        This is undesirable because {reason}.\n    validations:\n      required: true\n  - type: textarea\n    id: steps-to-reproduce\n    attributes:\n      label: Steps to reproduce\n      description: Write a step by step list that will allow us to reproduce this bug.\n      placeholder: |\n        1. Do something\n        2. Then do something else\n    validations:\n      required: true\n  - type: textarea\n    id: additional-info\n    attributes:\n      label: Additional information\n      description: If you have some additional information, please write it here.\n    validations:\n      required: false\n  - type: checkboxes\n    id: terms\n    attributes:\n      label: Code of Conduct\n      description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/sherlock-project/sherlock/blob/master/docs/CODE_OF_CONDUCT.md). \n      options:\n        - label: I agree to follow this project's Code of Conduct\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/false-negative.yml",
    "content": "name: False negative\ndescription: Report a site that is returning false negative results\ntitle: \"False negative for: \"\nlabels: [\"false negative\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Please include the site name in the title of your issue.\n        Submit **one site per report** for faster resolution. If you have multiple sites in the same report, it often takes longer to fix.\n  - type: textarea\n    id: additional-info\n    attributes:\n      label: Additional info\n      description: If you know why the site is returning false negatives, or noticed any patterns, please explain.\n      placeholder: |\n        Reddit is returning false negatives because...\n    validations:\n      required: false\n  - type: checkboxes\n    id: terms\n    attributes:\n      label: Code of Conduct\n      description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/sherlock-project/sherlock/blob/master/docs/CODE_OF_CONDUCT.md). \n      options:\n        - label: I agree to follow this project's Code of Conduct\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/false-positive.yml",
    "content": "name: False positive\ndescription: Report a site that is returning false positive results\ntitle: \"False positive for: \"\nlabels: [\"false positive\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Please include the site name in the title of your issue.\n        Submit **one site per report** for faster resolution. If you have multiple sites in the same report, it often takes longer to fix.\n  - type: textarea\n    id: additional-info\n    attributes:\n      label: Additional info\n      description: If you know why the site is returning false positives, or noticed any patterns, please explain.\n      placeholder: |\n        Reddit is returning false positives because...\n        False positives only occur after x searches...\n    validations:\n      required: false\n  - type: checkboxes\n    id: terms\n    attributes:\n      label: Code of Conduct\n      description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/sherlock-project/sherlock/blob/master/docs/CODE_OF_CONDUCT.md). \n      options:\n        - label: I agree to follow this project's Code of Conduct\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.yml",
    "content": "name: Feature request\ndescription: Request a feature or enhancement\nlabels: [\"enhancement\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Concise and thoughtful titles help other contributors find and add your requested feature.\n  - type: textarea\n    id: description\n    attributes:\n      label: Description\n      description: Describe the feature you are requesting\n      placeholder: I'd like Sherlock to be able to do xyz\n    validations:\n      required: true\n  - type: checkboxes\n    id: terms\n    attributes:\n      label: Code of Conduct\n      description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/sherlock-project/sherlock/blob/master/docs/CODE_OF_CONDUCT.md). \n      options:\n        - label: I agree to follow this project's Code of Conduct\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/site-request.yml",
    "content": "name: Reuest a new website\ndescription: Request that Sherlock add support for a new website\ntitle: \"Requesting support for: \"\nlabels: [\"site support request\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Ensure that the site name is in the title of your request. Requests without this information will be **closed**.\n  - type: input\n    id: site-url\n    attributes:\n      label: Site URL\n      description: |\n        What is the URL of the website indicated in your title?\n        Websites sometimes have similar names. This helps constributors find the correct site.\n      placeholder: https://reddit.com\n    validations:\n      required: true\n  - type: textarea\n    id: additional-info\n    attributes:\n      label: Additional info\n      description: If you have suggestions on how Sherlock should detect for usernames, please explain below\n      placeholder: Sherlock can detect if a username exists on Reddit by checking for...\n    validations:\n      required: false\n  - type: checkboxes\n    id: terms\n    attributes:\n      label: Code of Conduct\n      description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/sherlock-project/sherlock/blob/master/docs/CODE_OF_CONDUCT.md). \n      options:\n        - label: I agree to follow this project's Code of Conduct\n          required: true\n"
  },
  {
    "path": ".github/SECURITY.md",
    "content": "## Security Policy\n\n### Supported Versions\n\nSherlock is a forward looking project. Only the latest and most current version is supported.\n\n### Reporting a Vulnerability\n\nSecurity concerns can be submitted [__here__][report-url] without risk of exposing sensitive information. For issues that are low severity or unlikely to see exploitation, public issues are often acceptable.\n\n[report-url]: https://github.com/sherlock-project/sherlock/security/advisories/new\n"
  },
  {
    "path": ".github/workflows/exclusions.yml",
    "content": "name: Exclusions Updater\n\non:\n  schedule:\n    #- cron: '0 5 * * 0'  # Runs at 05:00 every Sunday\n    - cron: '0 5 * * *' # Runs at 05:00 every day\n  workflow_dispatch:\n\njobs:\n  update-exclusions:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v5\n\n      - name: Set up Python\n        uses: actions/setup-python@v6\n        with:\n          python-version: '3.13'\n\n      - name: Install Poetry\n        uses: abatilo/actions-poetry@v4\n        with:\n          poetry-version: 'latest'\n\n      - name: Install dependencies\n        run: |\n          poetry install --no-interaction --with dev\n\n      - name: Run false positive tests\n        run: |\n          $(poetry env activate)\n          pytest -q --tb no -m validate_targets_fp -n 20 | tee fp_test_results.txt\n          deactivate\n\n      - name: Parse false positive detections by desired categories\n        run: |\n          grep -oP '(?<=test_false_pos\\[)[^\\]]+(?=\\].*result was Claimed)' fp_test_results.txt \\\n            | sort -u > false_positive_exclusions.txt\n          grep -oP '(?<=test_false_pos\\[)[^\\]]+(?=\\].*result was WAF)' fp_test_results.txt \\\n            | sort -u > waf_hits.txt\n\n      - name: Detect if exclusions list changed\n        id: detect_changes\n        run: |\n          git fetch origin exclusions || true\n\n          if git show origin/exclusions:false_positive_exclusions.txt >/dev/null 2>&1; then\n            # If the exclusions branch and file exist, compare\n            if git diff --quiet origin/exclusions -- false_positive_exclusions.txt; then\n              echo \"exclusions_changed=false\" >> \"$GITHUB_OUTPUT\"\n            else\n              echo \"exclusions_changed=true\" >> \"$GITHUB_OUTPUT\"\n            fi\n          else\n            # If the exclusions branch or file do not exist, treat as changed\n            echo \"exclusions_changed=true\" >> \"$GITHUB_OUTPUT\"\n          fi\n\n      - name: Quantify and display results\n        run: |\n          FP_COUNT=$(wc -l < false_positive_exclusions.txt | xargs)\n          WAF_COUNT=$(wc -l < waf_hits.txt | xargs)\n          echo \">>> Found $FP_COUNT false positives and $WAF_COUNT WAF hits.\"\n          echo \">>> False positive exclusions:\" && cat false_positive_exclusions.txt\n          echo \">>> WAF hits:\" && cat waf_hits.txt\n\n      - name: Commit and push exclusions list\n        if: steps.detect_changes.outputs.exclusions_changed == 'true'\n        run: |\n          git config user.name \"Paul Pfeister (automation)\"\n          git config user.email \"code@pfeister.dev\"\n\n          mv false_positive_exclusions.txt false_positive_exclusions.txt.tmp\n\n          git add -f false_positive_exclusions.txt.tmp # -f required to override .gitignore\n          git stash push -m \"stash false positive exclusion list\" -- false_positive_exclusions.txt.tmp\n\n          git fetch origin exclusions || true # Allows creation of branch if deleted\n          git checkout -B exclusions origin/exclusions || (git checkout --orphan exclusions && git rm -rf .)\n\n          git stash pop || true\n\n          mv false_positive_exclusions.txt.tmp false_positive_exclusions.txt\n\n          git rm -f false_positive_exclusions.txt.tmp || true\n          git add false_positive_exclusions.txt\n          git commit -m \"auto: update exclusions list\" || echo \"No changes to commit\"\n          git push origin exclusions\n"
  },
  {
    "path": ".github/workflows/regression.yml",
    "content": "name: Regression Testing\n\non:\n  pull_request:\n    branches:\n      - master\n      - release/**\n    paths:\n      - '.github/workflows/regression.yml'\n      - '**/*.json'\n      - '**/*.py'\n      - '**/*.ini'\n      - '**/*.toml'\n      - 'Dockerfile'\n  push:\n    branches:\n      - master\n      - release/**\n    paths:\n      - '.github/workflows/regression.yml'\n      - '**/*.json'\n      - '**/*.py'\n      - '**/*.ini'\n      - '**/*.toml'\n      - 'Dockerfile'\n\njobs:\n  tox-lint:\n    runs-on: ubuntu-latest\n    # Linting is run through tox to ensure that the same linter\n    # is used by local runners\n    steps:\n      - uses: actions/checkout@v6\n      - name: Set up linting environment\n        uses: actions/setup-python@v6\n        with:\n          python-version: '3.x'\n      - name: Install tox and related dependencies\n        run: |\n          python -m pip install --upgrade pip\n          pip install tox\n      - name: Run tox linting environment\n        run: tox -e lint\n  tox-matrix:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      # We want to know what specific versions it fails on\n      fail-fast: false\n      matrix:\n        os: [\n          ubuntu-latest,\n          windows-latest,\n          macos-latest,\n        ]\n        python-version: [\n          '3.10',\n          '3.11',\n          '3.12',\n          '3.13',\n          '3.14',\n          '3.14t',\n        ]\n    steps:\n      - uses: actions/checkout@v6\n      - name: Set up environment ${{ matrix.python-version }}\n        uses: actions/setup-python@v6\n        with:\n          python-version: ${{ matrix.python-version }}\n      - name: Install tox and related dependencies\n        run: |\n          python -m pip install --upgrade pip\n          pip install tox\n          pip install tox-gh-actions\n      - name: Run tox\n        run: tox\n  docker-build-test:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v6\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      - name: Get version from pyproject.toml\n        id: get-version\n        run: |\n          VERSION=$(grep -m1 'version = ' pyproject.toml | cut -d'\"' -f2)\n          echo \"version=$VERSION\" >> $GITHUB_OUTPUT\n      - name: Build Docker image\n        run: |\n          docker build \\\n            --build-arg VERSION_TAG=${{ steps.get-version.outputs.version }} \\\n            -t sherlock-test:latest .\n      - name: Test Docker image runs\n        run: docker run --rm sherlock-test:latest --version\n"
  },
  {
    "path": ".github/workflows/update-site-list.yml",
    "content": "name: Update Site List\n\n# Trigger the workflow when changes are pushed to the main branch\n# and the changes include the sherlock_project/resources/data.json file\non:\n  push:\n    branches:\n      - master\n    paths:\n      - sherlock_project/resources/data.json\n\njobs:\n  sync-json-data:\n    # Use the latest version of Ubuntu as the runner environment\n    runs-on: ubuntu-latest\n\n    steps:\n      # Check out the code at the specified pull request head commit\n      - name: Checkout code\n        uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.pull_request.head.sha }}\n          fetch-depth: 0\n\n      # Install Python 3\n      - name: Install Python\n        uses: actions/setup-python@v5\n        with:\n          python-version: '3.x'\n\n      # Execute the site_list.py Python script\n      - name: Execute site-list.py\n        run: python devel/site-list.py\n\n      - name: Pushes to another repository\n        uses: sdushantha/github-action-push-to-another-repository@main\n        env:\n          SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }}\n          API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }}\n        with:\n          source-directory: 'output'\n          destination-github-username: 'sherlock-project'\n          commit-message: 'Updated site list'\n          destination-repository-name: 'sherlockproject.xyz'\n          user-email: siddharth.dushantha@gmail.com\n          target-branch: master\n"
  },
  {
    "path": ".github/workflows/validate_modified_targets.yml",
    "content": "name: Modified Target Validation\n\non:\n  pull_request_target:\n    branches:\n      - master\n    paths:\n      - \"sherlock_project/resources/data.json\"\n\njobs:\n  validate-modified-targets:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      pull-requests: write\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v5\n        with:\n          # Checkout the base branch but fetch all history to avoid a second fetch call\n          ref: ${{ github.base_ref }}\n          fetch-depth: 0\n\n      - name: Set up Python\n        uses: actions/setup-python@v6\n        with:\n          python-version: \"3.13\"\n\n      - name: Install Poetry\n        uses: abatilo/actions-poetry@v4\n        with:\n          poetry-version: \"latest\"\n\n      - name: Install dependencies\n        run: |\n          poetry install --no-interaction --with dev\n\n      - name: Prepare JSON versions for comparison\n        run: |\n          # Fetch only the PR's branch head (single network call in this step)\n          git fetch origin pull/${{ github.event.pull_request.number }}/head:pr\n\n          # Find the merge-base commit between the target branch and the PR branch\n          MERGE_BASE=$(git merge-base origin/${{ github.base_ref }} pr)\n          echo \"Comparing PR head against merge-base commit: $MERGE_BASE\"\n\n          # Safely extract the file from the PR's head and the merge-base commit\n          git show pr:sherlock_project/resources/data.json > data.json.head\n          git show $MERGE_BASE:sherlock_project/resources/data.json > data.json.base\n\n          # CRITICAL FIX: Overwrite the checked-out data.json with the one from the PR\n          # This ensures that pytest runs against the new, updated file.\n          cp data.json.head sherlock_project/resources/data.json\n\n      - name: Discover modified targets\n        id: discover-modified\n        run: |\n          CHANGED=$(\n            python - <<'EOF'\n          import json\n          import sys\n          try:\n              with open(\"data.json.base\") as f: base = json.load(f)\n              with open(\"data.json.head\") as f: head = json.load(f)\n          except FileNotFoundError as e:\n              print(f\"Error: Could not find {e.filename}\", file=sys.stderr)\n              sys.exit(1)\n          except json.JSONDecodeError as e:\n              print(f\"Error: Could not decode JSON from a file - {e}\", file=sys.stderr)\n              sys.exit(1)\n\n          changed = []\n          for k, v in head.items():\n              if k not in base or base[k] != v:\n                  changed.append(k)\n\n          print(\",\".join(sorted(changed)))\n          EOF\n          )\n\n          # Preserve changelist\n          echo -e \">>> Changed targets: \\n$(echo $CHANGED | tr ',' '\\n')\"\n          echo \"changed_targets=$CHANGED\" >> \"$GITHUB_OUTPUT\"\n\n      - name: Validate remote manifest against local schema\n        if: steps.discover-modified.outputs.changed_targets != ''\n        run: |\n          poetry run pytest tests/test_manifest.py::test_validate_manifest_against_local_schema\n\n      # --- The rest of the steps below are unchanged ---\n\n      - name: Validate modified targets\n        if: steps.discover-modified.outputs.changed_targets != ''\n        continue-on-error: true\n        run: |\n          poetry run pytest -q --tb no -rA -m validate_targets -n 20 \\\n            --chunked-sites \"${{ steps.discover-modified.outputs.changed_targets }}\" \\\n            --junitxml=validation_results.xml\n\n      - name: Prepare validation summary\n        if: steps.discover-modified.outputs.changed_targets != ''\n        id: prepare-summary\n        run: |\n          summary=$(\n            poetry run python devel/summarize_site_validation.py validation_results.xml || echo \"Failed to generate summary of test results\"\n          )\n          echo \"$summary\" > validation_summary.md\n\n      - name: Announce validation results\n        if: steps.discover-modified.outputs.changed_targets != ''\n        uses: actions/github-script@v8\n        with:\n          script: |\n            const fs = require('fs');\n            const body = fs.readFileSync('validation_summary.md', 'utf8');\n            await github.rest.issues.createComment({\n              issue_number: context.payload.pull_request.number,\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              body: body,\n            });\n\n      - name: This step shows as ran when no modifications are found\n        if: steps.discover-modified.outputs.changed_targets == ''\n        run: |\n          echo \"No modified targets found\"\n"
  },
  {
    "path": ".gitignore",
    "content": "# Virtual Environments\nvenv/\nbin/\nlib/\npyvenv.cfg\npoetry.lock\n\n# Regression Testing\n.coverage\n.tox/\n\n# Editor Configurations\n.vscode/\n.idea/\n\n# Python\n__pycache__/\n\n# Pip\nsrc/\n\n# Devel, Build, and Installation\n*.egg-info/\ndist/**\n\n# Jupyter Notebook\n.ipynb_checkpoints\n*.ipynb\n\n# Output files, except requirements.txt\n*.txt\n!requirements.txt\n\n# Comma-Separated Values (CSV) Reports\n*.csv\n\n#XLSX Reports\n*.xlsx\n\n# Excluded sites list\ntests/.excluded_sites\n\n# MacOS Folder Metadata File\n.DS_Store\n\n# Vim swap files\n*.swp\n"
  },
  {
    "path": "Dockerfile",
    "content": "# Release instructions:\n  # 1. Update the version tag in the Dockerfile to match the version in sherlock/__init__.py\n  # 2. Update the VCS_REF tag to match the tagged version's FULL commit hash\n  # 3. Build image with BOTH latest and version tags\n    # i.e. `docker build -t sherlock/sherlock:0.16.0 -t sherlock/sherlock:latest .`\n\nFROM python:3.12-slim-bullseye AS build\nWORKDIR /sherlock\n\nRUN pip3 install --no-cache-dir --upgrade pip\n\nFROM python:3.12-slim-bullseye\nWORKDIR /sherlock\n\nARG VCS_REF= # CHANGE ME ON UPDATE\nARG VCS_URL=\"https://github.com/sherlock-project/sherlock\"\nARG VERSION_TAG= # CHANGE ME ON UPDATE\n\nENV SHERLOCK_ENV=docker\n\nLABEL org.label-schema.vcs-ref=$VCS_REF \\\n      org.label-schema.vcs-url=$VCS_URL \\\n      org.label-schema.name=\"Sherlock\" \\\n      org.label-schema.version=$VERSION_TAG \\\n      website=\"https://sherlockproject.xyz\"\n\nRUN pip3 install --no-cache-dir sherlock-project==$VERSION_TAG\n\nWORKDIR /sherlock\n\nENTRYPOINT [\"sherlock\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 Sherlock Project\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "devel/site-list.py",
    "content": "#!/usr/bin/env python\n# This module generates the listing of supported sites which can be found in\n# sites.mdx. It also organizes all the sites in alphanumeric order\nimport json\nimport os\n\nDATA_REL_URI: str = \"sherlock_project/resources/data.json\"\n\nDEFAULT_ENCODING = \"utf-8\"\n\n# Read the data.json file\nwith open(DATA_REL_URI, \"r\", encoding=DEFAULT_ENCODING) as data_file:\n    data: dict = json.load(data_file)\n\n# Removes schema-specific keywords for proper processing\nsocial_networks = data.copy()\nsocial_networks.pop('$schema', None)\n\n# Sort the social networks in alphanumeric order\nsocial_networks = sorted(social_networks.items())\n\n# Make output dir where the site list will be written\nos.mkdir(\"output\")\n\n# Write the list of supported sites to sites.mdx\nwith open(\"output/sites.mdx\", \"w\", encoding=DEFAULT_ENCODING) as site_file:\n    site_file.write(\"---\\n\")\n    site_file.write(\"title: 'List of supported sites'\\n\")\n    site_file.write(\"sidebarTitle: 'Supported sites'\\n\")\n    site_file.write(\"icon: 'globe'\\n\")\n    site_file.write(\"description: 'Sherlock currently supports **400+** sites'\\n\")\n    site_file.write(\"---\\n\\n\")\n\n    for social_network, info in social_networks:\n        url_main = info[\"urlMain\"]\n        is_nsfw = \"**(NSFW)**\" if info.get(\"isNSFW\") else \"\"\n        site_file.write(f\"1. [{social_network}]({url_main}) {is_nsfw}\\n\")\n\n# Overwrite the data.json file with sorted data\nwith open(DATA_REL_URI, \"w\", encoding=DEFAULT_ENCODING) as data_file:\n    sorted_data = json.dumps(data, indent=2, sort_keys=True)\n    data_file.write(sorted_data)\n    data_file.write(\"\\n\")  # Keep the newline after writing data\n\nprint(\"Finished updating supported site listing!\")\n"
  },
  {
    "path": "devel/summarize_site_validation.py",
    "content": "#!/usr/bin/env python\n# This module summarizes the results of site validation tests queued by\n# workflow validate_modified_targets for presentation in Issue comments.\n\nfrom defusedxml import ElementTree as ET\nimport sys\nfrom pathlib import Path\n\ndef summarize_junit_xml(xml_path: Path) -> str:\n    tree = ET.parse(xml_path)\n    root = tree.getroot()\n    suite = root.find('testsuite')\n\n    pass_message: str = \":heavy_check_mark: &nbsp; Pass\"\n    fail_message: str = \":x: &nbsp; Fail\"\n\n    if suite is None:\n        raise ValueError(\"Invalid JUnit XML: No testsuite found\")\n\n    summary_lines: list[str] = []\n    summary_lines.append(\"#### Automatic validation of changes\\n\")\n    summary_lines.append(\"| Target | F+ Check | F- Check |\")\n    summary_lines.append(\"|---|---|---|\")\n\n    failures = int(suite.get('failures', 0))\n    errors_detected: bool = False\n\n    results: dict[str, dict[str, str]] = {}\n\n    for testcase in suite.findall('testcase'):\n        test_name = testcase.get('name').split('[')[0]\n        site_name = testcase.get('name').split('[')[1].rstrip(']')\n        failure = testcase.find('failure')\n        error = testcase.find('error')\n\n        if site_name not in results:\n            results[site_name] = {}\n\n        if test_name == \"test_false_neg\":\n            results[site_name]['F- Check'] = pass_message if failure is None and error is None else fail_message\n        elif test_name == \"test_false_pos\":\n            results[site_name]['F+ Check'] = pass_message if failure is None and error is None else fail_message\n\n        if error is not None:\n            errors_detected = True\n\n    for result in results:\n        summary_lines.append(f\"| {result} | {results[result].get('F+ Check', 'Error!')} | {results[result].get('F- Check', 'Error!')} |\")\n\n    if failures > 0:\n        summary_lines.append(\"\\n___\\n\" +\n            \"\\nFailures were detected on at least one updated target. Commits containing accuracy failures\" +\n            \" will often not be merged (unless a rationale is provided, such as false negatives due to regional differences).\")\n\n    if errors_detected:\n        summary_lines.append(\"\\n___\\n\" +\n            \"\\n**Errors were detected during validation. Please review the workflow logs.**\")\n\n    return \"\\n\".join(summary_lines)\n\nif __name__ == \"__main__\":\n    if len(sys.argv) != 2:\n        print(\"Usage: summarize_site_validation.py <junit-xml-file>\")\n        sys.exit(1)\n\n    xml_path: Path = Path(sys.argv[1])\n    if not xml_path.is_file():\n        print(f\"Error: File '{xml_path}' does not exist.\")\n        sys.exit(1)\n\n    summary: str = summarize_junit_xml(xml_path)\n    print(summary)\n"
  },
  {
    "path": "docs/CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, caste, color, religion, or sexual\nidentity and orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the overall\n  community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or advances of\n  any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email address,\n  without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at yahya.arbabi@gmail.com.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series of\nactions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or permanent\nban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior, harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within the\ncommunity.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.1, available at\n[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].\n\nCommunity Impact Guidelines were inspired by\n[Mozilla's code of conduct enforcement ladder][Mozilla CoC].\n\nFor answers to common questions about this code of conduct, see the FAQ at\n[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at\n[https://www.contributor-covenant.org/translations][translations].\n\n[homepage]: https://www.contributor-covenant.org\n[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html\n[Mozilla CoC]: https://github.com/mozilla/diversity\n[FAQ]: https://www.contributor-covenant.org/faq\n[translations]: https://www.contributor-covenant.org/translations"
  },
  {
    "path": "docs/README.md",
    "content": "<p align=\"center\">\n  <br>\n  <a href=\"https://sherlock-project.github.io/\" target=\"_blank\"><img src=\"images/sherlock-logo.png\" alt=\"sherlock\"/></a>\n  <br>\n  <span>Hunt down social media accounts by username across <a href=\"https://sherlockproject.xyz/sites\">400+ social networks</a></span>\n  <br>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://sherlockproject.xyz/installation\">Installation</a>\n  &nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;\n  <a href=\"https://sherlockproject.xyz/usage\">Usage</a>\n  &nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;\n  <a href=\"https://sherlockproject.xyz/contribute\">Contributing</a>\n</p>\n\n<p align=\"center\">\n<img width=\"70%\" height=\"70%\" src=\"images/demo.png\" alt=\"demo\"/>\n</p>\n\n\n## Installation\n\n> [!WARNING]  \n> Packages for ParrotOS and Ubuntu 24.04, maintained by a third party, appear to be __broken__.  \n> Users of these systems should defer to pipx/pip or Docker.\n\n| Method | Notes |\n| - | - |\n| `pipx install sherlock-project` | `pip` may be used in place of `pipx` |\n| `docker run -it --rm sherlock/sherlock` |\n| `dnf install sherlock-project` | |\n\nCommunity-maintained packages are available for Debian (>= 13), Ubuntu (>= 22.10), Homebrew, Kali, and BlackArch. These packages are not directly supported or maintained by the Sherlock Project.\n\nSee all alternative installation methods [here](https://sherlockproject.xyz/installation)\n\n## General usage\n\nTo search for only one user:\n```bash\nsherlock user123\n```\n\nTo search for more than one user:\n```bash\nsherlock user1 user2 user3\n```\n\nAccounts found will be stored in an individual text file with the corresponding username (e.g ```user123.txt```).\n\n```console\n$ sherlock --help\nusage: sherlock [-h] [--version] [--verbose] [--folderoutput FOLDEROUTPUT]\n                [--output OUTPUT] [--tor] [--unique-tor] [--csv] [--xlsx]\n                [--site SITE_NAME] [--proxy PROXY_URL] [--json JSON_FILE]\n                [--timeout TIMEOUT] [--print-all] [--print-found] [--no-color]\n                [--browse] [--local] [--nsfw]\n                USERNAMES [USERNAMES ...]\n\nSherlock: Find Usernames Across Social Networks (Version 0.14.3)\n\npositional arguments:\n  USERNAMES             One or more usernames to check with social networks.\n                        Check similar usernames using {?} (replace to '_', '-', '.').\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --version             Display version information and dependencies.\n  --verbose, -v, -d, --debug\n                        Display extra debugging information and metrics.\n  --folderoutput FOLDEROUTPUT, -fo FOLDEROUTPUT\n                        If using multiple usernames, the output of the results will be\n                        saved to this folder.\n  --output OUTPUT, -o OUTPUT\n                        If using single username, the output of the result will be saved\n                        to this file.\n  --tor, -t             Make requests over Tor; increases runtime; requires Tor to be\n                        installed and in system path.\n  --unique-tor, -u      Make requests over Tor with new Tor circuit after each request;\n                        increases runtime; requires Tor to be installed and in system\n                        path.\n  --csv                 Create Comma-Separated Values (CSV) File.\n  --xlsx                Create the standard file for the modern Microsoft Excel\n                        spreadsheet (xlsx).\n  --site SITE_NAME      Limit analysis to just the listed sites. Add multiple options to\n                        specify more than one site.\n  --proxy PROXY_URL, -p PROXY_URL\n                        Make requests over a proxy. e.g. socks5://127.0.0.1:1080\n  --json JSON_FILE, -j JSON_FILE\n                        Load data from a JSON file or an online, valid, JSON file.\n  --timeout TIMEOUT     Time (in seconds) to wait for response to requests (Default: 60)\n  --print-all           Output sites where the username was not found.\n  --print-found         Output sites where the username was found.\n  --no-color            Don't color terminal output\n  --browse, -b          Browse to all results on default browser.\n  --local, -l           Force the use of the local data.json file.\n  --nsfw                Include checking of NSFW sites from default list.\n```\n## Apify Actor Usage [![Sherlock Actor](https://apify.com/actor-badge?actor=netmilk/sherlock)](https://apify.com/netmilk/sherlock?fpr=sherlock)\n\n<a href=\"https://apify.com/netmilk/sherlock?fpr=sherlock\"><img src=\"https://apify.com/ext/run-on-apify.png\" alt=\"Run Sherlock Actor on Apify\" width=\"176\" height=\"39\" /></a>\n\nYou can run Sherlock in the cloud without installation using the [Sherlock Actor](https://apify.com/netmilk/sherlock?fpr=sherlock) on [Apify](https://apify.com?fpr=sherlock) free of charge.\n\n``` bash\n$ echo '{\"usernames\":[\"user123\"]}' | apify call -so netmilk/sherlock\n[{\n  \"username\": \"user123\",\n  \"links\": [\n    \"https://www.1337x.to/user/user123/\",\n    ...\n  ]\n}]\n```\n\nRead more about the [Sherlock Actor](../.actor/README.md), including how to use it programmatically via the Apify [API](https://apify.com/netmilk/sherlock/api?fpr=sherlock), [CLI](https://docs.apify.com/cli/?fpr=sherlock) and [JS/TS and Python SDKs](https://docs.apify.com/sdk?fpr=sherlock).\n\n## Credits\n\nThank you to everyone who has contributed to Sherlock! ❤️\n\n<a href=\"https://github.com/sherlock-project/sherlock/graphs/contributors\">\n  <img src=\"https://contrib.rocks/image?&columns=25&max=10000&&repo=sherlock-project/sherlock\" alt=\"contributors\"/>\n</a>\n\n## Star History\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/svg?repos=sherlock-project/sherlock&type=Date&theme=dark\" />\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/svg?repos=sherlock-project/sherlock&type=Date\" />\n  <img alt=\"Sherlock Project Star History Chart\" src=\"https://api.star-history.com/svg?repos=sherlock-project/sherlock&type=Date\" />\n</picture>\n\n## License\n\nMIT © Sherlock Project<br/>\nOriginal Creator - [Siddharth Dushantha](https://github.com/sdushantha)\n\n<!-- Reference Links -->\n\n[ext_pypi]: https://pypi.org/project/sherlock-project/\n[ext_brew]: https://formulae.brew.sh/formula/sherlock\n"
  },
  {
    "path": "docs/pyproject/README.md",
    "content": "<!-- This README should be a mini version at all times for use on pypi -->\n\n<p align=center>\n  <br>\n  <a href=\"https://sherlock-project.github.io/\" target=\"_blank\"><img src=\"https://www.kali.org/tools/sherlock/images/sherlock-logo.svg\" width=\"25%\"/></a>\n  <br>\n  <strong><span>Hunt down social media accounts by username across <a href=\"https://github.com/sherlock-project/sherlock/blob/master/sites.md\">400+ social networks</a></span></strong>\n  <br><br>\n  <span>Additional documentation can be found at our <a href=\"https://github.com/sherlock-project/sherlock/\">GitHub repository</a></span>\n  <br>\n</p>\n\n## Usage\n\n```console\n$ sherlock --help\nusage: sherlock [-h] [--version] [--verbose] [--folderoutput FOLDEROUTPUT]\n                [--output OUTPUT] [--tor] [--unique-tor] [--csv] [--xlsx]\n                [--site SITE_NAME] [--proxy PROXY_URL] [--json JSON_FILE]\n                [--timeout TIMEOUT] [--print-all] [--print-found] [--no-color]\n                [--browse] [--local] [--nsfw]\n                USERNAMES [USERNAMES ...]\n```\n\nTo search for only one user:\n```bash\n$ sherlock user123\n```\n\nTo search for more than one user:\n```bash\n$ sherlock user1 user2 user3\n```\n<br>\n\n___\n\n<br>\n<p align=\"center\">\n<img width=\"70%\" height=\"70%\" src=\"https://user-images.githubusercontent.com/27065646/219638267-a5e11090-aa6e-4e77-87f7-0e95f6ad5978.png\"/>\n</a>\n</p>\n"
  },
  {
    "path": "docs/removed-sites.md",
    "content": "# List Of Sites Removed From Sherlock\n\nThis is a list of sites implemented in such a way that the current design of\nSherlock is not capable of determining if a given username exists or not.\nThey are listed here in the hope that things may change in the future\nso they may be re-included.\n\n\n## gpodder.net\n\nAs of 2020-05-25, all usernames are reported as available.\n\nThe server is returning a HTTP Status 500 (Internal server error)\nfor all queries.\n\n```json\n  \"gpodder.net\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 2013984,\n    \"url\": \"https://gpodder.net/user/{}\",\n    \"urlMain\": \"https://gpodder.net/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n\n## Investing.com\n\nAs of 2020-05-25, all usernames are reported as claimed.\n\nAny query against a user seems to be redirecting to a general\ninformation page at https://www.investing.com/brokers/.  Probably\nrequired login before access.\n\n```json\n  \"Investing.com\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 196,\n    \"url\": \"https://www.investing.com/traders/{}\",\n    \"urlMain\": \"https://www.investing.com/\",\n    \"username_claimed\": \"jenny\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## AdobeForums\n\nAs of 2020-04-12, all usernames are reported as available.\n\nWhen I went to the site to see what was going on, usernames that I know\nexisted were redirecting to the main page.\n\nI was able to see user profiles without logging in, but the URL was not\nrelated to their user name.  For example, user \"tomke\" went to\nhttps://community.adobe.com/t5/user/viewprofilepage/user-id/10882613.\nThis can be detected, but it requires a different detection method.\n\n```json\n  \"AdobeForums\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 59,\n    \"url\": \"https://forums.adobe.com/people/{}\",\n    \"urlMain\": \"https://forums.adobe.com/\",\n    \"username_claimed\": \"jack\",\n    \"username_unclaimed\": \"noonewouldeverusethis77777\"\n  },\n```\n\n## Basecamp\n\nAs of 2020-02-23, all usernames are reported as not existing.\n\n\n```json\n  \"Basecamp\": {\n    \"errorMsg\": \"The account you were looking for doesn't exist\",\n    \"errorType\": \"message\",\n    \"rank\": 4914,\n    \"url\": \"https://{}.basecamphq.com\",\n    \"urlMain\": \"https://basecamp.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Canva\n\nAs of 2020-02-23, all usernames are reported as not existing.\n\n```json\n  \"Canva\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://www.canva.com/{}\",\n    \"rank\": 128,\n    \"url\": \"https://www.canva.com/{}\",\n    \"urlMain\": \"https://www.canva.com/\",\n    \"username_claimed\": \"jenny\",\n    \"username_unclaimed\": \"xgtrq\"\n  },\n```\n\n## Pixabay\n\nAs of 2020-01-21, all usernames are reported as not existing.\n\n```json\n  \"Pixabay\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 378,\n    \"url\": \"https://pixabay.com/en/users/{}\",\n    \"urlMain\": \"https://pixabay.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## NPM-Packages\n\nNPM-Packages are not users.\n\n```json\n  \"NPM-Package\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.npmjs.com/package/{}\",\n    \"urlMain\": \"https://www.npmjs.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Pexels\n\nAs of 2020-01-21, all usernames are reported as not existing.\n\n```json\n  \"Pexels\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 745,\n    \"url\": \"https://www.pexels.com/@{}\",\n    \"urlMain\": \"https://www.pexels.com/\",\n    \"username_claimed\": \"bruno\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## RamblerDating\n\nAs of 2019-12-31, site always times out.\n\n```json\n  \"RamblerDating\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://dating.rambler.ru/page/{}\",\n    \"rank\": 322,\n    \"url\": \"https://dating.rambler.ru/page/{}\",\n    \"urlMain\": \"https://dating.rambler.ru/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## YandexMarket\n\nAs of 2019-12-31, all usernames are reported as existing.\n\n```json\n  \"YandexMarket\": {\n    \"errorMsg\": \"\\u0422\\u0443\\u0442 \\u043d\\u0438\\u0447\\u0435\\u0433\\u043e \\u043d\\u0435\\u0442\",\n    \"errorType\": \"message\",\n    \"rank\": 47,\n    \"url\": \"https://market.yandex.ru/user/{}/achievements\",\n    \"urlMain\": \"https://market.yandex.ru/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Codementor\n\nAs of 2019-12-31, usernames that exist are not detected.\n\n```json\n  \"Codementor\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 10252,\n    \"url\": \"https://www.codementor.io/@{}\",\n    \"urlMain\": \"https://www.codementor.io/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## KiwiFarms\n\nAs of 2019-12-31, the site gives a 403 for all usernames.  You have to\nbe logged into see a profile.\n\n```json\n  \"KiwiFarms\": {\n    \"errorMsg\": \"The specified member cannot be found\",\n    \"errorType\": \"message\",\n    \"rank\": 38737,\n    \"url\": \"https://kiwifarms.net/members/?username={}\",\n    \"urlMain\": \"https://kiwifarms.net/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis\"\n  },\n```\n\n## Teknik\n\nAs of 2019-11-30, the site causes Sherlock to just hang.\n\n```json\n  \"Teknik\": {\n    \"errorMsg\": \"The user does not exist\",\n    \"errorType\": \"message\",\n    \"rank\": 357163,\n    \"url\": \"https://user.teknik.io/{}\",\n    \"urlMain\": \"https://teknik.io/\",\n    \"username_claimed\": \"red\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n\n## Shockwave\n\nAs of 2019-11-28, usernames that exist give a 503 \"Service Unavailable\"\nHTTP Status.\n\n```json\n  \"Shockwave\": {\n    \"errorMsg\": \"Oh no! You just finished all of the games on the internet!\",\n    \"errorType\": \"message\",\n    \"rank\": 35916,\n    \"url\": \"http://www.shockwave.com/member/profiles/{}.jsp\",\n    \"urlMain\": \"http://www.shockwave.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis\"\n  },\n```\n\n## Foursquare\n\nWhen usage of automated tool is detected. Whole IP is banned from future requests.\nThere is an error message:\n\n> Please verify you are a human\n> Access to this page has been denied because we believe you are using automation tools to browse the website.\n\n```json\n  \"Foursquare\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 1843,\n    \"url\": \"https://foursquare.com/{}\",\n    \"urlMain\": \"https://foursquare.com/\",\n    \"username_claimed\": \"dens\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Khan Academy\n\nUsernames that don't exist are detected.  First noticed 2019-10-25.\n\n```json\n  \"Khan Academy\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 377,\n    \"url\": \"https://www.khanacademy.org/profile/{}\",\n    \"urlMain\": \"https://www.khanacademy.org/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n\n## EVE Online\n\nUsernames that exist are not detected.\n\n```json\n  \"EVE Online\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://eveonline.com\",\n    \"rank\": 15347,\n    \"url\": \"https://evewho.com/pilot/{}/\",\n    \"urlMain\": \"https://eveonline.com\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## AngelList\n\nUsernames that exist are not detected. Forbidden Request 403 Error.\n\n```json\n  \"AngelList\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 5767,\n    \"url\": \"https://angel.co/u/{}\",\n    \"urlMain\": \"https://angel.co/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## PowerShell Gallery\n\nAccidentally merged even though the original pull request showed that all\nuser names were available.\n\n```json\n  \"PowerShell Gallery\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 163562,\n    \"url\": \"https://www.powershellgallery.com/profiles/{}\",\n    \"urlMain\": \"https://www.powershellgallery.com\",\n    \"username_claimed\": \"powershellteam\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## StreamMe\n\nOn 2019-04-07, I get a Timed Out message from the website.  It has not\nbeen working earlier either (for some weeks).  It takes about 21s before\nthe site finally times out, so it really makes getting the results from\nSherlock a pain.\n\nIf the site becomes available in the future, we can put it back in.\n\n```json\n  \"StreamMe\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 31702,\n    \"url\": \"https://www.stream.me/{}\",\n    \"urlMain\": \"https://www.stream.me/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## BlackPlanet\n\nThis site has always returned a false positive.  The site returns the exact\nsame text for a claimed or an unclaimed username.  The site must be rendering\nall of the different content using Javascript in the browser.  So, there is\nno way distinguish between the results with the current design of Sherlock.\n\n```json\n  \"BlackPlanet\": {\n    \"errorMsg\": \"My Hits\",\n    \"errorType\": \"message\",\n    \"rank\": 110021,\n    \"url\": \"http://blackplanet.com/{}\",\n    \"urlMain\": \"http://blackplanet.com/\"\n  },\n```\n\n## Fotolog\n\nAround 2019-02-09, I get a 502 HTTP error (bad gateway) for any access.  On\n2019-03-10, the site is up, but it is in maintenance mode.\n\nIt does not seem to be working, so there is no sense in including it in\nSherlock.\n\n```json\n  \"Fotolog\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 47777,\n    \"url\": \"https://fotolog.com/{}\",\n    \"urlMain\": \"https://fotolog.com/\"\n  },\n```\n\n## Google Plus\n\nOn 2019-04-02, Google shutdown Google Plus.  While the content for some\nusers is available after that point, it is going away.  And, no one will\nbe able to create a new account.  So, there is no value is keeping it in\nSherlock.\n\nGood-bye [Google Plus](https://en.wikipedia.org/wiki/Google%2B)...\n\n```json\n  \"Google Plus\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 1,\n    \"url\": \"https://plus.google.com/+{}\",\n    \"urlMain\": \"https://plus.google.com/\",\n    \"username_claimed\": \"davidbrin1\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n\n## InsaneJournal\n\nAs of 2020-02-23, InsaneJournal returns false positive, when providing a username which contains a period.\nSince we were not able to find the criteria for a valid username, the best thing to do now is to remove it.\n\n```json\n  \"InsaneJournal\": {\n    \"errorMsg\": \"Unknown user\",\n    \"errorType\": \"message\",\n    \"rank\": 29728,\n    \"url\": \"http://{}.insanejournal.com/profile\",\n    \"urlMain\": \"insanejournal.com\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"dlyr6cd\"\n  },\n```\n\n## Sports Tracker\n\nAs of 2020-04-02, Sports Tracker returns false positives. Checking with `errorMsg` and `response_url`\ndid not seem to work.\n\n```\n   \"SportsTracker\": {\n     \"errorUrl\": \"https://www.sports-tracker.com/page-not-found\",\n     \"errorType\": \"response_url\",\n     \"rank\": 93950,\n     \"url\": \"https://www.sports-tracker.com/view_profile/{}\",\n     \"urlMain\": \"https://www.sports-tracker.com/\",\n     \"username_claimed\": \"blue\",\n     \"username_unclaimed\": \"noonewouldeveruse\"\n   },\n```\n\n## Trip\n\nAs of 2020-04-02, Trip by Skyscanner seems to not work beceause it keeps on\nredirecting to skyscanner.com whether the username exists or not.\n\n```json\n  \"Trip\": {\n      \"errorType\": \"status_code\",\n      \"rank\": 2847,\n      \"url\": \"https://www.trip.skyscanner.com/user/{}\",\n      \"urlMain\": \"https://www.trip.skyscanner.com/\",\n      \"username_claimed\": \"blue\",\n      \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n\n```\n\n## boingboing.net\n\nAs of 2020-04-02, boingboing.net requires a login to check if a user exits or not.\n\n```\n   \"boingboing.net\": {\n     \"errorType\": \"status_code\",\n     \"rank\": 5821,\n     \"url\": \"https://bbs.boingboing.net/u/{}\",\n     \"urlMain\": \"https://boingboing.net/\",\n     \"username_claimed\": \"admin\",\n     \"username_unclaimed\": \"noonewouldeverusethis7\"\n   },\n```\n\n## elwoRU\nAs of 2020-04-04, elwoRu does not exist anymore. I confirmed using\ndownforeveryoneorjustme.com that the website is down.\n\n```json\n  \"elwoRU\": {\n    \"errorMsg\": \"\\u041f\\u043e\\u043b\\u044c\\u0437\\u043e\\u0432\\u0430\\u0442\\u0435\\u043b\\u044c \\u043d\\u0435 \\u043d\\u0430\\u0439\\u0434\\u0435\\u043d\",\n    \"errorType\": \"message\",\n    \"rank\": 254810,\n    \"url\": \"https://elwo.ru/index/8-0-{}\",\n    \"urlMain\": \"https://elwo.ru/\",\n    \"username_claimed\": \"red\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## ingvarr.net.ru\n\nAs of 2020-04-04, ingvarr.net.ru does not exist anymore. I confirmed using\ndownforeveryoneorjustme.com that the website is down.\n\n```json\n  \"ingvarr.net.ru\": {\n    \"errorMsg\": \"\\u041f\\u043e\\u043b\\u044c\\u0437\\u043e\\u0432\\u0430\\u0442\\u0435\\u043b\\u044c \\u043d\\u0435 \\u043d\\u0430\\u0439\\u0434\\u0435\\u043d\",\n    \"errorType\": \"message\",\n    \"rank\": 107721,\n    \"url\": \"http://ingvarr.net.ru/index/8-0-{}\",\n    \"urlMain\": \"http://ingvarr.net.ru/\",\n    \"username_claimed\": \"red\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Redsun.tf\n\nAs of 2020-06-20, Redsun.tf seems to be adding random digits to the end of the usernames which makes it pretty much impossible\nfor Sherlock to check for usernames on this particular website.\n\n```json\n  \"Redsun.tf\": {\n    \"errorMsg\": \"The specified member cannot be found\",\n    \"errorType\": \"message\",\n    \"rank\": 3796657,\n    \"url\": \"https://forum.redsun.tf/members/?username={}\",\n    \"urlMain\": \"https://redsun.tf/\",\n    \"username_claimed\": \"dan\",\n    \"username_unclaimed\": \"noonewouldeverusethis\"\n  },\n```\n\n## Creative Market\n\nAs of 2020-06-20, Creative Market has a captcha to prove that you are a human, and because of this\nSherlock is unable to check for username on this site because we will always get  a page which asks\nus to prove that we are not a robot.\n\n```json\n  \"CreativeMarket\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 1896,\n    \"url\": \"https://creativemarket.com/users/{}\",\n    \"urlMain\": \"https://creativemarket.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## pvpru\n\nAs of 2020-06-20, pvpru uses CloudFlair, and because of this we get a \"Access denied\" error whenever\nwe try to check for a username.\n\n```json\n  \"pvpru\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 405547,\n    \"url\": \"https://pvpru.com/board/member.php?username={}&tab=aboutme#aboutme\",\n    \"urlMain\": \"https://pvpru.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## easyen\nAs of 2020-06-21, easyen returns false positives when using a username which contains\na period. Since we could not find the criteria for the usernames for this site, it will be\nremoved\n\n```json\n  \"easyen\": {\n    \"errorMsg\": \"\\u041f\\u043e\\u043b\\u044c\\u0437\\u043e\\u0432\\u0430\\u0442\\u0435\\u043b\\u044c \\u043d\\u0435 \\u043d\\u0430\\u0439\\u0434\\u0435\\u043d\",\n    \"errorType\": \"message\",\n    \"rank\": 11564,\n    \"url\": \"https://easyen.ru/index/8-0-{}\",\n    \"urlMain\": \"https://easyen.ru/\",\n    \"username_claimed\": \"wd\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## pedsovet\nAs of 2020-06-21, pedsovet returns false positives when using a username which contains\na period. Since we could not find the criteria for the usernames for this site, it will be\nremoved\n\n```json\n  \"pedsovet\": {\n    \"errorMsg\": \"\\u041f\\u043e\\u043b\\u044c\\u0437\\u043e\\u0432\\u0430\\u0442\\u0435\\u043b\\u044c \\u043d\\u0435 \\u043d\\u0430\\u0439\\u0434\\u0435\\u043d\",\n    \"errorType\": \"message\",\n    \"rank\": 6776,\n    \"url\": \"http://pedsovet.su/index/8-0-{}\",\n    \"urlMain\": \"http://pedsovet.su/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n\n## radioskot\nAs of 2020-06-21, radioskot returns false positives when using a username which contains\na period. Since we could not find the criteria for the usernames for this site, it will be\nremoved\n```json\n  \"radioskot\": {\n    \"errorMsg\": \"\\u041f\\u043e\\u043b\\u044c\\u0437\\u043e\\u0432\\u0430\\u0442\\u0435\\u043b\\u044c \\u043d\\u0435 \\u043d\\u0430\\u0439\\u0434\\u0435\\u043d\",\n    \"errorType\": \"message\",\n    \"rank\": 105878,\n    \"url\": \"https://radioskot.ru/index/8-0-{}\",\n    \"urlMain\": \"https://radioskot.ru/\",\n    \"username_claimed\": \"red\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n\n\n## Coderwall\nAs of 2020-07-06, Coderwall returns false positives when checking for an username which contains a period.\nI have tried to find out what Coderwall's criteria is for a valid username, but unfortunately I have not been able to\nfind it and because of this, the best thing we can do now is to remove it.\n```json\n  \"Coderwall\": {\n    \"errorMsg\": \"404! Our feels when that url is used\",\n    \"errorType\": \"message\",\n    \"rank\": 11256,\n    \"url\": \"https://coderwall.com/{}\",\n    \"urlMain\": \"https://coderwall.com/\",\n    \"username_claimed\": \"jenny\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n\n\n## TamTam\nAs of 2020-07-06, TamTam returns false positives when given a username which contains a period\n```json\n  \"TamTam\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://tamtam.chat/\",\n    \"rank\": 87903,\n    \"url\": \"https://tamtam.chat/{}\",\n    \"urlMain\": \"https://tamtam.chat/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Zomato\nAs of 2020-07-24, Zomato seems to be unstable. Majority of the time, Zomato takes a very long time to respond.\n```json\n  \"Zomato\": {\n    \"errorType\": \"status_code\",\n    \"headers\": {\n      \"Accept-Language\": \"en-US,en;q=0.9\"\n    },\n    \"rank\": 1920,\n    \"url\": \"https://www.zomato.com/pl/{}/foodjourney\",\n    \"urlMain\": \"https://www.zomato.com/\",\n    \"username_claimed\": \"deepigoyal\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Mixer\nAs of 2020-07-22, the Mixer service has closed down.\n```json\n  \"mixer.com\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 1544,\n    \"url\": \"https://mixer.com/{}\",\n    \"urlMain\": \"https://mixer.com/\",\n    \"urlProbe\": \"https://mixer.com/api/v1/channels/{}\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n\n## KanoWorld\nAs of 2020-07-22, KanoWorld's api.kano.me subdomain no longer exists which makes it not possible for us check for usernames.\nIf an alternative way to check for usernames is found then it will added.\n```json\n  \"KanoWorld\": {\n    \"errorType\": \"status_code\",\n    \"rank\": 181933,\n    \"url\": \"https://api.kano.me/progress/user/{}\",\n    \"urlMain\": \"https://world.kano.me/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## YandexCollection\nAs of 2020-08-11, YandexCollection presents us with a recaptcha which prevents us from checking for usernames\n```json\n  \"YandexCollection\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://yandex.ru/collections/user/{}/\",\n    \"urlMain\": \"https://yandex.ru/collections/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## PayPal\n\nAs of 2020-08-24, PayPal now returns false positives, which was found when running the tests, but will most likley be added again in the near\nfuture once we find a better error detecting method.\n```json\n  \"PayPal\": {\n    \"errorMsg\": \"<meta name=\\\"twitter:title\\\" content=\\\"Get your very own PayPal.Me link\\\" />\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.paypal.com/paypalme/{}\",\n    \"headers\": {\n      \"User-Agent\": \"\"\n    },\n    \"urlMain\": \"https://www.paypal.me/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noneownsthisusername7\"\n  },\n```\n\n## ImageShack\n\nAs of 2020-08-24, ImageShack now returns false positives, which was found when running the tests, but will most likley be added again in the near future once we find a better error detecting method.\n```json\n  \"ImageShack\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://imageshack.us/\",\n    \"url\": \"https://imageshack.us/user/{}\",\n    \"urlMain\": \"https://imageshack.us/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Aptoide\n\nAs of 2020-08-24, Aptoide now returns false positives, which was found when running the tests, but will most likley be added again in the near\nfuture once we find a better error detecting method.\n```json\n  \"Aptoide\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://{}.en.aptoide.com/\",\n    \"urlMain\": \"https://en.aptoide.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Crunchyroll\n\nAs of 2020-08-24, Crunchyroll now returns false positives, which was found when running the tests, but will most likley be added again in the near future once we find a better error detecting method.\n\n```json\n  \"Crunchyroll\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.crunchyroll.com/user/{}\",\n    \"urlMain\": \"https://www.crunchyroll.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## T-MobileSupport\nAs of 2020-08-24, T-MobileSupport now returns false positives, which was found when running the tests, but will most likley be added again in the near future once we find a better error detecting method.\n\n```json\n  \"T-MobileSupport\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://support.t-mobile.com/people/{}\",\n    \"urlMain\": \"https://support.t-mobile.com\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## OpenCollective\n\nAs of 2020-08-24, OpenCollective now returns false positives, which was found when running the tests, but will most likley be added again in the near future once we find a better error detecting method.\n\n```json\n  \"OpenCollective\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://opencollective.com/{}\",\n    \"urlMain\": \"https://opencollective.com/\",\n    \"username_claimed\": \"sindresorhus\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## SegmentFault\n\nAs of 2020-08-24, SegmentFault now returns false positives, which was found when running the tests, but will most likley be added again in the near future once we find a better error detecting method.\n\n```json\n  \"SegmentFault\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://segmentfault.com/u/{}\",\n    \"urlMain\": \"https://segmentfault.com/\",\n    \"username_claimed\": \"bule\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Viadeo\n\nAs of 2020-08-24, Viadeo now returns false positives, which was found when running the tests, but will most likley be added again in the near future once we find a fix for this\n\n```json\n  \"Viadeo\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"http://fr.viadeo.com/en/profile/{}\",\n    \"urlMain\": \"http://fr.viadeo.com/en/\",\n    \"username_claimed\": \"franck.patissier\",\n    \"username_unclaimed\": \"noonewouldeverusethis\"\n  },\n```\n\n## MeetMe\n\nAs of 2020-09-02, MeetMe returns false positives\n\n```json\n  \"MeetMe\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://www.meetme.com/\",\n    \"url\": \"https://www.meetme.com/{}\",\n    \"urlMain\": \"https://www.meetme.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Linkdedin\n\nAs of 2020-09-23, Linkedin returns false positives because we are prompted with prompted to login when checking for a user\n\n```json\n  \"Linkedin\": {\n    \"errorMsg\": \"could not be found\",\n    \"errorType\": \"message\",\n    \"rank\": 0,\n    \"url\": \"https://www.linkedin.com/in/{}\",\n    \"urlMain\": \"https://www.linkedin.com/\",\n    \"username_claimed\": \"alex\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## tracr.co\nAs of 2020-09-23, tracr.co returns false positives because the site seems to be shut down.\n```json\n  \"tracr.co\": {\n    \"errorMsg\": \"No search results\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[A-Za-z0-9]{2,32}$\",\n    \"url\": \"https://tracr.co/users/1/{}\",\n    \"urlMain\": \"https://tracr.co/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n\n## Taringa\n\nAs of 2020-09-23, Taringa returns false positives.\n\n```json\n  \"Taringa\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[^.]*$\",\n    \"url\": \"https://www.taringa.net/{}\",\n    \"urlMain\": \"https://taringa.net/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Photobucket\nAs of 2020-10-21, Photobucket return false positives. This was reported in #785.\n```json\n  \"Photobucket\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://photobucket.com/user/{}/library\",\n    \"urlMain\": \"https://photobucket.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## 4PDA\nAs of 2020-10-21, 4PDA returns false positives. This was reported in #784.\n\n```json\n  \"4pda\": {\n    \"errorMsg\": \"[1,false,0]\",\n    \"errorType\": \"message\",\n    \"url\": \"https://4pda.ru/forum/index.php?act=search&source=pst&noform=1&username={}\",\n    \"urlMain\": \"https://4pda.ru/\",\n    \"urlProbe\": \" https://4pda.ru/forum/index.php?act=auth&action=chkname&login={}\",\n    \"username_claimed\": \"green\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## PokerStrategy\nAs of 2020-10-21, PokerStrategy returns false positives. This was reported in #776.\n```json\n  \"PokerStrategy\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"http://www.pokerstrategy.net/user/{}/profile/\",\n    \"urlMain\": \"http://www.pokerstrategy.net\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Filmogs\n\nFilmogs has closed down.\n\n> **Filmogs is closed**\n> **31-Aug 2020** - We are preparing the last data export and collection of images. It will be published here by 19-Oct 2020. If you have requested an export of your data it will also be emailed to you by 19-Oct 2020.\n\n```json\n  \"Filmogs\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.filmo.gs/users/{}\",\n    \"urlMain\": \"https://www.filmo.gs/\",\n    \"username_claimed\": \"cupparober\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## 500px\nAs of 2021-01-13, 500px returns false positives. This will hopefully be fixed soon once we add the ability to add different\nrequest methods.\n\n```json\n  \"500px\": {\n    \"errorMsg\": \"No message available\",\n    \"errorType\": \"message\",\n    \"url\": \"https://500px.com/p/{}\",\n    \"urlMain\": \"https://500px.com/\",\n    \"urlProbe\": \"https://api.500px.com/graphql?operationName=ProfileRendererQuery&variables=%7B%22username%22%3A%22{}%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%224d02ff5c13927a3ac73b3eef306490508bc765956940c31051468cf30402a503%22%7D%7D\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Badoo\nAs of 2021-01-13, Badoo returns false positives\n```json\n  \"Badoo\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://badoo.com/profile/{}\",\n    \"urlMain\": \"https://badoo.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Pling\nAs of 2021-01-13, Pling returns false positives.\n```json\n  \"Pling\": {\n    \"errorMsg\": \"Resource not found\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.pling.com/u/{}/\",\n    \"urlMain\": \"https://www.pling.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis\"\n  },\n```\n\n## Realmeye\nAs of 2021-01-13, Realmeye returns false positives.\n```json\n  \"Realmeye\": {\n    \"errorMsg\": \"Sorry, but we either:\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.realmeye.com/player/{}\",\n    \"urlMain\": \"https://www.realmeye.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Travellerspoint\nAs of 2021-01-13, Travellerspoint returns false positives\n```json\n  \"Travellerspoint\": {\n    \"errorMsg\": \"Wooops. Sorry!\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.travellerspoint.com/users/{}\",\n    \"urlMain\": \"https://www.travellerspoint.com\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## GDProfiles\n\nAs of 2021-06-27, GDProfiles takes way too long to respond. Must be an issue on their side.\n```json\n  \"GDProfiles\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://gdprofiles.com/{}\",\n    \"urlMain\": \"https://gdprofiles.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis\"\n  },\n```\n\n## AllTrails\n\nAs of 2021-06-27, AllTrails has a captcha which prevents us from checking for usernames on the site.\n```json\n  \"AllTrails\": {\n    \"errorMsg\": \"class=\\\"home index\\\"\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.alltrails.com/members/{}\",\n    \"urlMain\": \"https://www.alltrails.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis\"\n  }\n```\n\n## Cent\n\nAs of 2021-06-27, there is not way of checking if a username exists on Cent\n\n```json\n  \"Cent\": {\n    \"errorMsg\": \"<title>Cent</title>\",\n    \"errorType\": \"message\",\n    \"url\": \"https://beta.cent.co/@{}\",\n    \"urlMain\": \"https://cent.co/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Anobii\n\nAs of 2021-06-27, Anobii returns false positives and there is no stable way of checking usernames.\n```\n\n  \"Anobii\": {\n    \"errorType\": \"response_url\",\n    \"url\": \"https://www.anobii.com/{}/profile\",\n    \"urlMain\": \"https://www.anobii.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n\n## Kali Community\n\nAs of 2021-06-27, Kali Community requires us to be logged in order to check if a user exists on their forum.\n\n```json\n  \"Kali community\": {\n    \"errorMsg\": \"This user has not registered and therefore does not have a profile to view.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://forums.kali.org/member.php?username={}\",\n    \"urlMain\": \"https://forums.kali.org/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n\n## NameMC\n\nAs of 2021-06-27, NameMC uses captcha through CloudFlare which prevents us from checking if usernames exists on the site.\n\n```json\n  \"NameMC (Minecraft.net skins)\": {\n    \"errorMsg\": \"Profiles: 0 results\",\n    \"errorType\": \"message\",\n    \"url\": \"https://namemc.com/profile/{}\",\n    \"urlMain\": \"https://namemc.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## SteamID\n\nAs of 2021-06-27, Steam uses captcha through CloudFlare which prevents us from checking if usernames exists on the site.\n```json\n  \"Steamid\": {\n    \"errorMsg\": \"<link rel=\\\"canonical\\\" href=\\\"https://steamid.uk\\\" />\",\n    \"errorType\": \"message\",\n    \"url\": \"https://steamid.uk/profile/{}\",\n    \"urlMain\": \"https://steamid.uk/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n\n\n## TripAdvisor\n\nAs of 2021-06-27, Trip takes too long to return a response. As of now, the reason is not known.\n```json\n  \"TripAdvisor\": {\n    \"errorMsg\": \"This page is on vacation\\u2026\",\n    \"errorType\": \"message\",\n    \"url\": \"https://tripadvisor.com/members/{}\",\n    \"urlMain\": \"https://tripadvisor.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n\n```\n\n### House Mixes\n\nAs of 2021-09-04, House Mixes has issues connecting causing Sherlock to freeze.\n```json\n  \"House-Mixes.com\": {\n    \"errorMsg\": \"Profile Not Found\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$\",\n    \"url\": \"https://www.house-mixes.com/profile/{}\",\n    \"urlMain\": \"https://www.house-mixes.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n\n### Quora\nAs of 2021-09-04, Quora returns false positives.\n```json\n  \"Quora\": {\n    \"errorMsg\": \"Page Not Found\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.quora.com/profile/{}\",\n    \"urlMain\": \"https://www.quora.com/\",\n    \"username_claimed\": \"Matt-Riggsby\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n\n### SparkPeople\nAs of 2021-09-04, SparkPeople returns false positives.\n```json\n  \"SparkPeople\": {\n    \"errorMsg\": \"We couldn't find that user\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.sparkpeople.com/mypage.asp?id={}\",\n    \"urlMain\": \"https://www.sparkpeople.com\",\n    \"username_claimed\": \"adam\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n\n### Cloob\nAs of 2021-10-25, Cloob seems to be down and their site is not responding.\n```json\n  \"Cloob\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.cloob.com/name/{}\",\n    \"urlMain\": \"https://www.cloob.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n\n### TM-Ladder\nAs of 2021-11-30, TM-Ladder is returning false positives due to rate limits.\n\n```json\n  \"TM-Ladder\": {\n    \"errorMsg\": \"player unknown or invalid\",\n    \"errorType\": \"message\",\n    \"url\": \"http://en.tm-ladder.com/{}_rech.php\",\n    \"urlMain\": \"http://en.tm-ladder.com/index.php\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis\"\n```\n\n### plug.dj\nAs of 2021-12-02, plug.dj is returning false positives because the service is down.\n\n```json\n  \"plug.dj\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://plug.dj/@/{}\",\n    \"urlMain\": \"https://plug.dj/\",\n    \"username_claimed\": \"plug-dj-rock\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n\n## Facenama\n\nAs of 2022-02-6, Facenama seems to be down their rebuilding their site\n```json\n  \"Facenama\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://facenama.com/404.html\",\n    \"regexCheck\": \"^[-a-zA-Z0-9_]+$\",\n    \"url\": \"https://facenama.com/{}\",\n    \"urlMain\": \"https://facenama.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis77\"\n  },\n```\n\n\n## Designspiration\n\nAs of 2022-04-17, Designspiration seems to be down or very laggy. Therefore, we're removing the site for now.\n\n```json\n  \"Designspiration\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.designspiration.net/{}/\",\n    \"urlMain\": \"https://www.designspiration.net/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## CapFriendly\n\nAs of 2022-05-01, CapFriendly always shows that a username exists even though it doesn't. This\nthen of course causes false positives in Sherlock's results.\n\n```json\n  \"CapFriendly\": {\n    \"errorMsg\": \"<div class=\\\"err show p5\\\">No results found</div>\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[a-zA-z][a-zA-Z0-9_]{2,79}$\",\n    \"url\": \"https://www.capfriendly.com/users/{}\",\n    \"urlMain\": \"https://www.capfriendly.com/\",\n    \"username_claimed\": \"thisactuallyexists\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Gab\n\nAs of 2022-05-01, Gab returns false positives because they now use CloudFlare\n```json\n  \"Gab\": {\n    \"errorMsg\": \"The page you are looking for isn't here.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://gab.com/{}\",\n    \"urlMain\": \"https://gab.com\",\n    \"username_claimed\": \"a\",\n    \"username_unclaimed\": \"noonewouldeverusethis\"\n  },\n```\n\n## FanCentro\n\nAs of 2022-05-1, FanCentro returns false positives. Will later in new version of Sherlock.\n\n```json\n  \"FanCentro\": {\n    \"errorMsg\": \"var environment\",\n    \"errorType\": \"message\",\n    \"url\": \"https://fancentro.com/{}\",\n    \"urlMain\": \"https://fancentro.com/\",\n    \"username_claimed\": \"nielsrosanna\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Smashcast\nAs og 2022-05-01, Smashcast is down\n```json\n  \"Smashcast\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.smashcast.tv/api/media/live/{}\",\n    \"urlMain\": \"https://www.smashcast.tv/\",\n    \"username_claimed\": \"hello\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Countable\n\nAs og 2022-05-01, Countable returns false positives\n```json\n  \"Countable\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.countable.us/{}\",\n    \"urlMain\": \"https://www.countable.us/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Raidforums\n\nRaidforums is [now run by the FBI](https://twitter.com/janomine/status/1499453777648234501?s=21)\n```json\n  \"Raidforums\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://raidforums.com/User-{}\",\n    \"urlMain\": \"https://raidforums.com/\",\n    \"username_claimed\": \"red\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Pinterest\nRemoved due to false positive\n\n```json\n  \"Pinterest\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.pinterest.com/{}/\",\n    \"urlMain\": \"https://www.pinterest.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis76543\"\n  }\n```\n\n## PCPartPicker\nAs of 17-07-2022, PCPartPicker requires us to login in order to check if a user exits\n\n```json\n  \"PCPartPicker\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://pcpartpicker.com/user/{}\",\n    \"urlMain\": \"https://pcpartpicker.com\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Ebay\nAs of 17-07-2022, Ebay is very slow to respond. It was also reported that it returned false positives. So this is something that has been investigated further later.\n\n```json\n  \"eBay.com\": {\n    \"errorMsg\": \"The User ID you entered was not found. Please check the User ID and try again.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.ebay.com/usr/{}\",\n    \"urlMain\": \"https://www.ebay.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n  \"eBay.de\": {\n    \"errorMsg\": \"Der eingegebene Nutzername wurde nicht gefunden. Bitte pr\\u00fcfen Sie den Nutzernamen und versuchen Sie es erneut.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.ebay.de/usr/{}\",\n    \"urlMain\": \"https://www.ebay.de/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Ghost\nAs of 17-07-2022, Ghost returns false positives\n\n```json\n  \"Ghost\": {\n    \"errorMsg\": \"Domain Error\",\n    \"errorType\": \"message\",\n    \"url\": \"https://{}.ghost.io/\",\n    \"urlMain\": \"https://ghost.org/\",\n    \"username_claimed\": \"troyhunt\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n\n## Atom Discussions\nAs of 25-07-2022, Atom Discussions seems to not work beceause it keeps on\nredirecting to github discussion tab which does not exist and is not specific to a username\n\n```json\n  \"Atom Discussions\": {\n    \"errorMsg\": \"Oops! That page doesn\\u2019t exist or is private.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://discuss.atom.io/u/{}/summary\",\n    \"urlMain\": \"https://discuss.atom.io\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis\"\n  }\n```\n\n## Gam1ng\nAs of 25-07-2022, Gam1ng has been permanently moved and is no longer functional\n\n```json\n  \"Gam1ng\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://gam1ng.com.br/user/{}\",\n    \"urlMain\": \"https://gam1ng.com.br\",\n    \"username_claimed\": \"PinKgirl\",\n    \"username_unclaimed\": \"noonewouldeverusethis77777\"\n  }\n```\n\n## OGUsers\nAs of 25-07-2022, OGUsers is now no longer functional\n\n```json\n  \"OGUsers\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://ogusers.com/{}\",\n    \"urlMain\": \"https://ogusers.com/\",\n    \"username_claimed\": \"ogusers\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n\n## Otzovik\nAs of 25-07-2022, Otzovik is now no longer functional\n\n```json\n  \"Otzovik\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://otzovik.com/profile/{}\",\n    \"urlMain\": \"https://otzovik.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n\n## radio_echo_msk\nAs of 25-07-2022, radio_echo_msk is now no longer functional\n\n```json\n  \"radio_echo_msk\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://echo.msk.ru/users/{}\",\n    \"urlMain\": \"https://echo.msk.ru/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n## Ello\nAs of 06.09.2022, Ello is now behind CloudFlare\n```json\n  \"Ello\": {\n    \"errorMsg\": \"We couldn't find the page you're looking for\",\n    \"errorType\": \"message\",\n    \"url\": \"https://ello.co/{}\",\n    \"urlMain\": \"https://ello.co/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  }\n```\n\n## GitHub Support Community\nAs of 06.09.2022, GitHub Support Community's endpoint just redirects to the main community page\n```json\n  \"GitHub Support Community\": {\n    \"errorMsg\": \"Oops! That page doesn\\u2019t exist or is private.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://github.community/u/{}/summary\",\n    \"urlMain\": \"https://github.community\",\n    \"username_claimed\": \"jperl\",\n    \"username_unclaimed\": \"noonewouldusethis298\"\n  }\n```\n\n## GuruShots\nAs of 08.09.2022, GuruShots returns false positives because it just returns a blank page. Need to look further into it so that it can be added back.\n\n```json\n  \"GuruShots\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://gurushots.com/{}/photos\",\n    \"urlMain\": \"https://gurushots.com/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Google Developer\nAs of 09.10.2022, Google Developer returns false positives. The site is dynamic so we're not abl to get any proper results\n\n```json\n  \"Google Developer\": {\n    \"errorMsg\": \"Sorry, the profile was not found.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://g.dev/{}\",\n    \"urlMain\": \"https://g.dev/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## mastodon.technology\nAs of 18.12.2022, mastodon.technology has no A/AAAA records and the [website was shut down by the owner](https://ashfurrow.com/blog/mastodon-technology-shutdown/).\n\n```json\n  \"mastodon.technology\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://mastodon.technology/@{}\",\n    \"urlMain\": \"https://mastodon.xyz/\",\n    \"username_claimed\": \"ashfurrow\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n\n## Aruino\nAs of 04.02.2023, Arduino returns false positives. Finding a fix is doable but takes some time. Will be fixed later\n\n```json\n\"Arduino\": {\n    \"errorMsg\":\"<title>Arduino Cloud</title>\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^(?![_-])[A-Za-z0-9_-]{3,}$\",\n    \"url\": \"https://projecthub.arduino.cc/{}\",\n    \"urlMain\": \"https://www.arduino.cc/\",\n    \"username_claimed\": \"blue\",\n    \"username_unclaimed\": \"noonewould\"\n  },\n\n```\n\n## Zoomit\nAs of 04.02.2023, Zoomit return false positves. An attempt at finding a fix was made but a lot of time was used without luck. Therefore, it wont be prioritized at the moment.\n```json\n  \"zoomit\": {\n    \"errorMsg\": \"\\u0645\\u062a\\u0627\\u0633\\u0641\\u0627\\u0646\\u0647 \\u0635\\u0641\\u062d\\u0647 \\u06cc\\u0627\\u0641\\u062a \\u0646\\u0634\\u062f\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.zoomit.ir/user/{}\",\n    \"urlMain\": \"https://www.zoomit.ir\",\n    \"username_claimed\": \"kossher\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## Facebook\nAs of 04.02.2023, Facebook returns false positives because we get prompted with the login screen to view the data\n```json\n\"Facebook\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z0-9\\\\.]{3,49}(?<!\\\\.com|\\\\.org|\\\\.net)$\",\n    \"url\": \"https://www.facebook.com/{}\",\n    \"urlMain\": \"https://www.facebook.com/\",\n    \"urlProbe\": \"https://www.facebook.com/{}/videos/\",\n    \"username_claimed\": \"hackerman\",\n    \"username_unclaimed\": \"noonewouldeverusethis7\"\n  },\n```\n\n## BinarySearch\nAs of 08.02.2023, BinarySearch seems to not be responding at all\n```json\n  \"BinarySearch\": {\n    \"errorMsg\": \"{}\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[a-zA-Z0-9-_]{1,15}$\",\n    \"url\": \"https://binarysearch.io/@/{}\",\n    \"urlMain\": \"https://binarysearch.io/\",\n    \"urlProbe\": \"https://binarysearch.io/api/users/{}/profile\",\n    \"username_claimed\": \"Eyes_Wide_Shut\"\n  },\n```\n## Arduino\nAs of 15.02.2023, Arduino returns false positives due to some unstable redirects\n```json\n  \"Arduino\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^(?![_-])[A-Za-z0-9_-]{3,}$\",\n    \"url\": \"https://create.arduino.cc/projecthub/{}\",\n    \"urlMain\": \"https://www.arduino.cc/\",\n    \"username_claimed\": \"blue\"\n  },\n```\n## Koo\nAs of 15.02.2023, Koo returns false positives\n```json\n  \"koo\": {\n    \"errorMsg\": \"This profile does not exist\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.kooapp.com/profile/{}\",\n    \"urlMain\": \"https://www.kooapp.com\",\n    \"urlProbe\": \"https://www.kooapp.com/apiV1/users/handle/{}/valid\",\n    \"username_claimed\": \"john\"\n  }\n```\n\n\n## We Heart It\nAs of  2022.02.25, WeHeartIt no longer allows us to check for usersnames through their website. Visiting their website leads to links to download the mobile application. A potential way of fixing this is to find API endpoints in the app\n```json\n  \"We Heart It\": {\n    \"errorMsg\": \"Oops! You've landed on a moving target!\",\n    \"errorType\": \"message\",\n    \"url\": \"https://weheartit.com/{}\",\n    \"urlMain\": \"https://weheartit.com/\",\n    \"username_claimed\": \"ventivogue\"\n  }\n```\n\n\n## Tinder\nAs of 2022.03.15, Tinder returns false positives. We will try to rev the API endpoint on the android app to find a better soon\n\n```json\n\"Tinder\": {\n    \"errorMsg\": [\n      \"<title data-react-helmet=\\\"true\\\">Tinder | Dating, Make Friends &amp; Meet New People</title>\",\n      \"<title data-react-helmet=\\\"true\\\">Tinder | Match. Chat. Date.</title>\"\n    ],\n    \"errorType\": \"message\",\n    \"url\": \"https://www.tinder.com/@{}\",\n    \"urlMain\": \"https://tinder.com/\",\n    \"username_claimed\": \"blue\"\n  },\n```\n\n\n## Coil\nAs of 2023.03.15, Coil has been discontinued. All accounts were deleted and any requests return a 404.\n\n```json\n\"Coil\": {\n    \"errorMsg\": \"User not found\",\n    \"errorType\": \"message\",\n    \"request_method\": \"POST\",\n    \"request_payload\": {\n      \"operationName\": \"getCreator\",\n      \"query\": \"query getCreator($userShortName:String!){getCreator(userShortName:$userShortName){id}}\",\n      \"variables\": {\n        \"userShortName\": \"{}\"\n      }\n    },\n    \"url\": \"https://coil.com/u/{}\",\n    \"urlMain\": \"https://coil.com/\",\n    \"urlProbe\": \"https://coil.com/gateway\",\n    \"username_claimed\": \"adam\"\n  }\n```\n\n## OnlyFans\nAs of 2023.04.20, OnlyFans returns false negatives on checking usernames with the API endpoint and directly through their website.\n\n```json\n\"OnlyFans\": {\n    \"errorType\": \"status_code\",\n    \"isNSFW\": true,\n    \"url\": \"https://onlyfans.com/{}\",\n    \"urlMain\": \"https://onlyfans.com/\",\n    \"urlProbe\": \"https://onlyfans.com/api2/v2/users/{}\",\n    \"username_claimed\": \"theemilylynne\"\n  }\n```\n\n## OK\nAs of 2023.04.21, Ok.ru returns false positives\n```json\n  \"OK\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z][a-zA-Z0-9_.-]*$\",\n    \"url\": \"https://ok.ru/{}\",\n    \"urlMain\": \"https://ok.ru/\",\n    \"username_claimed\": \"ok\"\n  }\n```\n\n## ForumhouseRU\nAs of 2023.04.21, ForumhouseRU returns false positives\n```json\n  \"forumhouseRU\": {\n    \"errorMsg\": \"\\u0423\\u043a\\u0430\\u0437\\u0430\\u043d\\u043d\\u044b\\u0439 \\u043f\\u043e\\u043b\\u044c\\u0437\\u043e\\u0432\\u0430\\u0442\\u0435\\u043b\\u044c \\u043d\\u0435 \\u043d\\u0430\\u0439\\u0434\\u0435\\u043d. \\u041f\\u043e\\u0436\\u0430\\u043b\\u0443\\u0439\\u0441\\u0442\\u0430, \\u0432\\u0432\\u0435\\u0434\\u0438\\u0442\\u0435 \\u0434\\u0440\\u0443\\u0433\\u043e\\u0435 \\u0438\\u043c\\u044f.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.forumhouse.ru/members/?username={}\",\n    \"urlMain\": \"https://www.forumhouse.ru/\",\n    \"username_claimed\": \"red\"\n  }\n```\n\n## Enjin\nAs of 2023.08.29, Enjin has closed down.\n\n```json\n\"Enjin\": {\n    \"errorMsg\": \"Yikes, there seems to have been an error. We've taken note and will check out the problem right away!\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.enjin.com/profile/{}\",\n    \"urlMain\": \"https://www.enjin.com/\",\n    \"username_claimed\": \"blue\"\n  },\n```\n\n## IRL\nAs of 2023.08.29, IRL has shut down\n```json\n  \"IRL\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.irl.com/{}\",\n    \"urlMain\": \"https://www.irl.com/\",\n    \"username_claimed\": \"hacker\"\n  }\n```\n\n## Munzee\nAs of 2023.08.29, Munzee requires us to be logged into the site in order to check if a user exists or not\n```json\n  \"Munzee\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.munzee.com/m/{}\",\n    \"urlMain\": \"https://www.munzee.com/\",\n    \"username_claimed\": \"blue\"\n  }\n```\n\n## Quizlet\nAs of 2023.08.29 Quizlet requires us to enable JavaScript to check if a user exsits on the website\n\n```json\n\"Quizlet\": {\n    \"errorMsg\": \"Page Unavailable\",\n    \"errorType\": \"message\",\n    \"url\": \"https://quizlet.com/{}\",\n    \"urlMain\": \"https://quizlet.com\",\n    \"username_claimed\": \"blue\"\n  }\n```\n\n## GunsAndAmmo\nAs of 2023.08.29, GunsAndAmmo responds with 404 from time to time\n```json\n  \"GunsAndAmmo\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://forums.gunsandammo.com/profile/{}\",\n    \"urlMain\": \"https://gunsandammo.com/\",\n    \"username_claimed\": \"adam\"\n  }\n```\n\n## TikTok\nAs of 2023.12.21, TikTok returns false positives. This is because the webpage returns a somewhat blank page. This prevents us from being able to check for the existence of usernames. Proxitok does not work either.\n\n```json\n  \"TikTok\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://tiktok.com/@{}\",\n    \"urlMain\": \"https://tiktok.com/\",\n    \"username_claimed\": \"red\"\n  },\n```\n\n## Lolchess\nAs of 2023.12.21, Lolchess returns false positives.\n```json\n  \"Lolchess\": {\n    \"errorMsg\": \"No search results\",\n    \"errorType\": \"message\",\n    \"url\": \"https://lolchess.gg/profile/na/{}\",\n    \"urlMain\": \"https://lolchess.gg/\",\n    \"username_claimed\": \"blue\"\n  },\n```\n\n## Virgool\nAs of 2023.12.21, Virgool returns false positives.\n```json\n  \"Virgool\": {\n    \"errorMsg\": \"\\u06f4\\u06f0\\u06f4\",\n    \"errorType\": \"message\",\n    \"url\": \"https://virgool.io/@{}\",\n    \"urlMain\": \"https://virgool.io/\",\n    \"username_claimed\": \"blue\"\n  },\n```\n\n## Whonix Forum\nAs of 2023.12.21, Whonix Forum returns false positives.\n```json\n  \"Whonix Forum\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://forums.whonix.org/u/{}/summary\",\n    \"urlMain\": \"https://forums.whonix.org/\",\n    \"username_claimed\": \"red\"\n  },\n```\n\n## Ebio\nAs of 2023.12.21, Ebio returns false positives.\n```json\n  \"ebio.gg\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://ebio.gg/{}\",\n    \"urlMain\": \"https:/ebio.gg\",\n    \"username_claimed\": \"dev\"\n  },\n```\n\n## HexRPG\n__2024-04-07 :__ HexRPG behind authentication wall. Unable to check usernames without logging in.\n```json\n  \"HexRPG\": {\n    \"errorMsg\": \"Error : User \",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[a-zA-Z0-9_ ]{3,20}$\",\n    \"url\": \"https://www.hexrpg.com/userinfo/{}\",\n    \"urlMain\": \"https://www.hexrpg.com/\",\n    \"username_claimed\": \"blue\"\n  }\n```\n\n## Oracle Communities\n__2024-04-07 :__ Oracle Communities behind authentication wall. Unable to check usernames without logging in.\n```json\n  \"Oracle Communities\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://community.oracle.com/people/{}\",\n    \"urlMain\": \"https://community.oracle.com\",\n    \"username_claimed\": \"dev\"\n  }\n```\n\n## Metacritic\n__2024-04-07 :__ Non-existent users seemingly displayed as real users with no activity. Needs adjustment.\n```json\n  \"metacritic\": {\n    \"errorMsg\": \"User not found\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^(?![-_].)[A-Za-z0-9-_]{3,15}$\",\n    \"url\": \"https://www.metacritic.com/user/{}\",\n    \"urlMain\": \"https://www.metacritic.com/\",\n    \"username_claimed\": \"blue\"\n  }\n```\n\n## G2G\n__2024-04-10 :__ Seems to be loading profiles with some wierd javascript setup that sherlock doesn't like, leading to difficult to control false positives\n```json\n  \"G2G\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://www.g2g.com/{}\",\n    \"regexCheck\": \"^[A-Za-z][A-Za-z0-9_]{2,11}$\",\n    \"url\": \"https://www.g2g.com/{}\",\n    \"urlMain\": \"https://www.g2g.com/\",\n    \"username_claimed\": \"user\"\n  }\n```\n\n## Bitcoin Forum\n__2024-04-24 :__ BCF seems to have gone defunct. Uncertain.\n```json\n\"BitCoinForum\": {\n    \"errorMsg\": \"The user whose profile you are trying to view does not exist.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://bitcoinforum.com/profile/{}\",\n    \"urlMain\": \"https://bitcoinforum.com\",\n    \"username_claimed\": \"bitcoinforum.com\"\n  }\n```\n\n## Zhihu\nAs of 24.06.2024, Zhihu returns false positives as they obfuscate the code thats returned. Checking for patterns may allow us to find a way to detect the existans of a user, this will be need to be worked on later\n```json\n\n  \"Zhihu\": {\n    \"errorMsg\": \"用户不存在\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.zhihu.com/people/{}\",\n    \"urlMain\": \"https://www.zhihu.com/\",\n    \"username_claimed\": \"blue\"\n  }\n```\n\n## Penetestit\n\nAs of 24.06.2024, Pentestit returns a 403. This is most likely due to a new site structures\n\n```json\n  \"labpentestit\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://lab.pentestit.ru/{}\",\n    \"url\": \"https://lab.pentestit.ru/profile/{}\",\n    \"urlMain\": \"https://lab.pentestit.ru/\",\n    \"username_claimed\": \"CSV\"\n  }\n```\n\n\n## Euw\n__2024-06-09 :__ errorMsg detection doesn't work anymore, because the error message is included in HTTP request body, even in successful search\n```json\n\"Euw\": {\n    \"errorMsg\": \"This summoner is not registered at OP.GG. Please check spelling.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://euw.op.gg/summoner/userName={}\",\n    \"urlMain\": \"https://euw.op.gg/\",\n    \"username_claimed\": \"blue\"\n  }\n```\n\n## Etsy\n__2024-06-10 :__ Http request returns 403 forbidden, and tries to verify the connection, so it doesn't work anymore\n```json\n\"Etsy\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.etsy.com/shop/{}\",\n    \"urlMain\": \"https://www.etsy.com/\",\n    \"username_claimed\": \"JennyKrafts\"\n  }\n```\n\n## Alik.cz\n__2024-07-21 :__ Target is now BLACKLISTED from the default manifest due to the site recieving unnecessarily high traffic from Sherlock (by request of the site owners). This target is not permitted to be reactivited. Inclusion in unrelated manifests is not impacted, but it is discouraged.\n\n## 8tracks\n__2025-02-02 :__ Might be dead again. Nobody knows for sure.\n```json\n\"8tracks\": {\n    \"errorType\": \"message\",\n    \"errorMsg\": \"\\\"available\\\":true\",\n    \"headers\": {\n      \"Accept-Language\": \"en-US,en;q=0.5\"\n    },\n    \"url\": \"https://8tracks.com/{}\",\n    \"urlProbe\": \"https://8tracks.com/users/check_username?login={}&format=jsonh\",\n    \"urlMain\": \"https://8tracks.com/\",\n    \"username_claimed\": \"blue\"\n  }\n```\n\n## Shpock\n__2025-02-02 :__ Can likely be added back with a new endpoint (source username availability endpoint from mobile app reg flow?)\n```json\n\"Shpock\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.shpock.com/shop/{}/items\",\n    \"urlMain\": \"https://www.shpock.com/\",\n    \"username_claimed\": \"user\"\n  }\n```\n\n## Twitch\n__2025-02-02 :__\n```json\n\"Twitch\": {\n    \"errorType\": \"message\",\n    \"errorMsg\": \"components.availability-tracking.warn-unavailable.component\",\n    \"url\": \"https://www.twitch.tv/{}\",\n    \"urlMain\": \"https://www.twitch.tv/\",\n    \"urlProbe\": \"https://m.twitch.tv/{}\",\n    \"username_claimed\": \"jenny\"\n  }\n```\n\n## Fiverr\n__2025-02-02 :__ Fiverr added CSRF protections that messed with this test\n```json\n\"Fiverr\": {\n    \"errorMsg\": \"\\\"status\\\":\\\"success\\\"\",\n    \"errorType\": \"message\",\n    \"headers\": {\n      \"Content-Type\": \"application/json\",\n      \"Accept-Language\": \"en-US,en;q=0.9\"\n    },\n    \"regexCheck\": \"^[A-Za-z][A-Za-z\\\\d_]{5,14}$\",\n    \"request_method\": \"POST\",\n    \"request_payload\": {\n      \"username\": \"{}\"\n    },\n    \"url\": \"https://www.fiverr.com/{}\",\n    \"urlMain\": \"https://www.fiverr.com/\",\n    \"urlProbe\": \"https://www.fiverr.com/validate_username\",\n    \"username_claimed\": \"blueman\"\n  }\n```\n\n## BabyRU\n__2025-02-02 :__ Just being problematic (possibly related to errorMsg encoding?)\n```json\n\"babyRU\": {\n    \"errorMsg\": [\n      \"\\u0421\\u0442\\u0440\\u0430\\u043d\\u0438\\u0446\\u0430, \\u043a\\u043e\\u0442\\u043e\\u0440\\u0443\\u044e \\u0432\\u044b \\u0438\\u0441\\u043a\\u0430\\u043b\\u0438, \\u043d\\u0435 \\u043d\\u0430\\u0439\\u0434\\u0435\\u043d\\u0430\",\n      \"Доступ с вашего IP-адреса временно ограничен\"\n    ],\n    \"errorType\": \"message\",\n    \"url\": \"https://www.baby.ru/u/{}/\",\n    \"urlMain\": \"https://www.baby.ru/\",\n    \"username_claimed\": \"blue\"\n  }\n```\n\n## v0.dev\n__2025-02-16 :__ Unsure if any way to view profiles exists now\n```json\n\"v0.dev\": {\n    \"errorType\": \"message\",\n    \"errorMsg\": \"<title>v0 by Vercel</title>\",\n    \"url\": \"https://v0.dev/{}\",\n    \"urlMain\": \"https://v0.dev\",\n    \"username_claimed\": \"t3dotgg\"\n  }\n```\n\n## TorrentGalaxy\n__2025-07-06 :__ Site appears to have gone offline in March and hasn't come back\n```json\n  \"TorrentGalaxy\": {\n    \"errorMsg\": \"<title>TGx:Can't show details</title>\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[A-Za-z0-9]{3,15}$\",\n    \"url\": \"https://torrentgalaxy.to/profile/{}\",\n    \"urlMain\": \"https://torrentgalaxy.to/\",\n    \"username_claimed\": \"GalaxyRG\"\n  },\n```\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[build-system]\nrequires = [ \"poetry-core>=1.2.0\" ]\nbuild-backend = \"poetry.core.masonry.api\"\n# poetry-core 1.8 not available in .fc39. Can upgrade to 1.8.0 at .fc39 EOL\n\n[tool.poetry-version-plugin]\nsource = \"init\"\n\n[tool.poetry]\nname = \"sherlock-project\"\nversion = \"0.16.0\"\ndescription = \"Hunt down social media accounts by username across social networks\"\nlicense = \"MIT\"\nauthors = [\n    \"Siddharth Dushantha <siddharth.dushantha@gmail.com>\"\n]\nmaintainers = [\n    \"Paul Pfeister <code@pfeister.dev>\",\n    \"Matheus Felipe <matheusfelipeog@protonmail.com>\",\n    \"Sondre Karlsen Dyrnes <sondre@villdyr.no>\"\n]\nreadme = \"docs/pyproject/README.md\"\npackages = [ { include = \"sherlock_project\"} ]\nkeywords = [ \"osint\", \"reconnaissance\", \"information gathering\" ]\nclassifiers = [\n    \"Development Status :: 5 - Production/Stable\",\n    \"Intended Audience :: Developers\",\n    \"Intended Audience :: Information Technology\",\n    \"Natural Language :: English\",\n    \"Operating System :: OS Independent\",\n    \"Programming Language :: Python :: 3\",\n    \"Programming Language :: Python :: 3.10\",\n    \"Programming Language :: Python :: 3.11\",\n    \"Programming Language :: Python :: 3.12\",\n    \"Programming Language :: Python :: 3.13\",\n    \"Topic :: Security\"\n]\nhomepage = \"https://sherlockproject.xyz/\"\nrepository = \"https://github.com/sherlock-project/sherlock\"\n\n\n[tool.poetry.urls]\n\"Bug Tracker\" = \"https://github.com/sherlock-project/sherlock/issues\"\n\n[tool.poetry.dependencies]\npython = \"^3.9\"\ncertifi = \">=2019.6.16\"\ncolorama = \"^0.4.1\"\nPySocks = \"^1.7.0\"\nrequests = \"^2.22.0\"\nrequests-futures = \"^1.0.0\"\nstem = \"^1.8.0\"\npandas = \"^2.2.1\"\nopenpyxl = \"^3.0.10\"\ntomli = \"^2.2.1\"\n\n[tool.poetry.group.dev.dependencies]\njsonschema = \"^4.0.0\"\nrstr = \"^3.2.2\"\npytest = \"^8.4.2\"\npytest-xdist = \"^3.8.0\"\n\n\n[tool.poetry.group.ci.dependencies]\ndefusedxml = \"^0.7.1\"\n\n[tool.poetry.scripts]\nsherlock = 'sherlock_project.sherlock:main'\n"
  },
  {
    "path": "pytest.ini",
    "content": "[pytest]\naddopts = --strict-markers -m \"not validate_targets\"\nmarkers =\n    online: mark tests are requiring internet access.\n    validate_targets: mark tests for sweeping manifest validation (sends many requests).\n    validate_targets_fp: validate_targets, false positive tests only.\n    validate_targets_fn: validate_targets, false negative tests only.\n"
  },
  {
    "path": "sherlock_project/__init__.py",
    "content": "\"\"\" Sherlock Module\n\nThis module contains the main logic to search for usernames at social\nnetworks.\n\n\"\"\"\n\nfrom importlib.metadata import version as pkg_version, PackageNotFoundError\nimport pathlib\nimport tomli\n\n\ndef get_version() -> str:\n    \"\"\"Fetch the version number of the installed package.\"\"\"\n    try:\n        return pkg_version(\"sherlock_project\")\n    except PackageNotFoundError:\n        pyproject_path: pathlib.Path = pathlib.Path(__file__).resolve().parent.parent / \"pyproject.toml\"\n        with pyproject_path.open(\"rb\") as f:\n            pyproject_data = tomli.load(f)\n        return pyproject_data[\"tool\"][\"poetry\"][\"version\"]\n\n# This variable is only used to check for ImportErrors induced by users running as script rather than as module or package\nimport_error_test_var = None\n\n__shortname__   = \"Sherlock\"\n__longname__    = \"Sherlock: Find Usernames Across Social Networks\"\n__version__     = get_version()\n\nforge_api_latest_release = \"https://api.github.com/repos/sherlock-project/sherlock/releases/latest\"\n"
  },
  {
    "path": "sherlock_project/__main__.py",
    "content": "#! /usr/bin/env python3\n\n\"\"\"\nSherlock: Find Usernames Across Social Networks Module\n\nThis module contains the main logic to search for usernames at social\nnetworks.\n\"\"\"\n\nimport sys\n\n\nif __name__ == \"__main__\":\n    # Check if the user is using the correct version of Python\n    python_version = sys.version.split()[0]\n\n    if sys.version_info < (3, 9):\n        print(f\"Sherlock requires Python 3.9+\\nYou are using Python {python_version}, which is not supported by Sherlock.\")\n        sys.exit(1)\n\n    from sherlock_project import sherlock\n    sherlock.main()\n"
  },
  {
    "path": "sherlock_project/notify.py",
    "content": "\"\"\"Sherlock Notify Module\n\nThis module defines the objects for notifying the caller about the\nresults of queries.\n\"\"\"\nfrom sherlock_project.result import QueryStatus\nfrom colorama import Fore, Style\nimport webbrowser\n\n# Global variable to count the number of results.\nglobvar = 0\n\n\nclass QueryNotify:\n    \"\"\"Query Notify Object.\n\n    Base class that describes methods available to notify the results of\n    a query.\n    It is intended that other classes inherit from this base class and\n    override the methods to implement specific functionality.\n    \"\"\"\n\n    def __init__(self, result=None):\n        \"\"\"Create Query Notify Object.\n\n        Contains information about a specific method of notifying the results\n        of a query.\n\n        Keyword Arguments:\n        self                   -- This object.\n        result                 -- Object of type QueryResult() containing\n                                  results for this query.\n\n        Return Value:\n        Nothing.\n        \"\"\"\n\n        self.result = result\n\n        # return\n\n    def start(self, message=None):\n        \"\"\"Notify Start.\n\n        Notify method for start of query.  This method will be called before\n        any queries are performed.  This method will typically be\n        overridden by higher level classes that will inherit from it.\n\n        Keyword Arguments:\n        self                   -- This object.\n        message                -- Object that is used to give context to start\n                                  of query.\n                                  Default is None.\n\n        Return Value:\n        Nothing.\n        \"\"\"\n\n        # return\n\n    def update(self, result):\n        \"\"\"Notify Update.\n\n        Notify method for query result.  This method will typically be\n        overridden by higher level classes that will inherit from it.\n\n        Keyword Arguments:\n        self                   -- This object.\n        result                 -- Object of type QueryResult() containing\n                                  results for this query.\n\n        Return Value:\n        Nothing.\n        \"\"\"\n\n        self.result = result\n\n        # return\n\n    def finish(self, message=None):\n        \"\"\"Notify Finish.\n\n        Notify method for finish of query.  This method will be called after\n        all queries have been performed.  This method will typically be\n        overridden by higher level classes that will inherit from it.\n\n        Keyword Arguments:\n        self                   -- This object.\n        message                -- Object that is used to give context to start\n                                  of query.\n                                  Default is None.\n\n        Return Value:\n        Nothing.\n        \"\"\"\n\n        # return\n\n    def __str__(self):\n        \"\"\"Convert Object To String.\n\n        Keyword Arguments:\n        self                   -- This object.\n\n        Return Value:\n        Nicely formatted string to get information about this object.\n        \"\"\"\n        return str(self.result)\n\n\nclass QueryNotifyPrint(QueryNotify):\n    \"\"\"Query Notify Print Object.\n\n    Query notify class that prints results.\n    \"\"\"\n\n    def __init__(self, result=None, verbose=False, print_all=False, browse=False):\n        \"\"\"Create Query Notify Print Object.\n\n        Contains information about a specific method of notifying the results\n        of a query.\n\n        Keyword Arguments:\n        self                   -- This object.\n        result                 -- Object of type QueryResult() containing\n                                  results for this query.\n        verbose                -- Boolean indicating whether to give verbose output.\n        print_all              -- Boolean indicating whether to only print all sites, including not found.\n        browse                 -- Boolean indicating whether to open found sites in a web browser.\n\n        Return Value:\n        Nothing.\n        \"\"\"\n\n        super().__init__(result)\n        self.verbose = verbose\n        self.print_all = print_all\n        self.browse = browse\n\n        return\n\n    def start(self, message):\n        \"\"\"Notify Start.\n\n        Will print the title to the standard output.\n\n        Keyword Arguments:\n        self                   -- This object.\n        message                -- String containing username that the series\n                                  of queries are about.\n\n        Return Value:\n        Nothing.\n        \"\"\"\n\n        title = \"Checking username\"\n\n        print(Style.BRIGHT + Fore.GREEN + \"[\" +\n              Fore.YELLOW + \"*\" +\n              Fore.GREEN + f\"] {title}\" +\n              Fore.WHITE + f\" {message}\" +\n              Fore.GREEN + \" on:\")\n        # An empty line between first line and the result(more clear output)\n        print('\\r')\n\n        return\n\n    def countResults(self):\n        \"\"\"This function counts the number of results. Every time the function is called,\n        the number of results is increasing.\n\n        Keyword Arguments:\n        self                   -- This object.\n\n        Return Value:\n        The number of results by the time we call the function.\n        \"\"\"\n        global globvar\n        globvar += 1\n        return globvar\n\n    def update(self, result):\n        \"\"\"Notify Update.\n\n        Will print the query result to the standard output.\n\n        Keyword Arguments:\n        self                   -- This object.\n        result                 -- Object of type QueryResult() containing\n                                  results for this query.\n\n        Return Value:\n        Nothing.\n        \"\"\"\n        self.result = result\n\n        response_time_text = \"\"\n        if self.result.query_time is not None and self.verbose is True:\n            response_time_text = f\" [{round(self.result.query_time * 1000)}ms]\"\n\n        # Output to the terminal is desired.\n        if result.status == QueryStatus.CLAIMED:\n            self.countResults()\n            print(Style.BRIGHT + Fore.WHITE + \"[\" +\n                  Fore.GREEN + \"+\" +\n                  Fore.WHITE + \"]\" +\n                  response_time_text +\n                  Fore.GREEN +\n                  f\" {self.result.site_name}: \" +\n                  Style.RESET_ALL +\n                  f\"{self.result.site_url_user}\")\n            if self.browse:\n                webbrowser.open(self.result.site_url_user, 2)\n\n        elif result.status == QueryStatus.AVAILABLE:\n            if self.print_all:\n                print(Style.BRIGHT + Fore.WHITE + \"[\" +\n                      Fore.RED + \"-\" +\n                      Fore.WHITE + \"]\" +\n                      response_time_text +\n                      Fore.GREEN + f\" {self.result.site_name}:\" +\n                      Fore.YELLOW + \" Not Found!\")\n\n        elif result.status == QueryStatus.UNKNOWN:\n            if self.print_all:\n                print(Style.BRIGHT + Fore.WHITE + \"[\" +\n                      Fore.RED + \"-\" +\n                      Fore.WHITE + \"]\" +\n                      Fore.GREEN + f\" {self.result.site_name}:\" +\n                      Fore.RED + f\" {self.result.context}\" +\n                      Fore.YELLOW + \" \")\n\n        elif result.status == QueryStatus.ILLEGAL:\n            if self.print_all:\n                msg = \"Illegal Username Format For This Site!\"\n                print(Style.BRIGHT + Fore.WHITE + \"[\" +\n                      Fore.RED + \"-\" +\n                      Fore.WHITE + \"]\" +\n                      Fore.GREEN + f\" {self.result.site_name}:\" +\n                      Fore.YELLOW + f\" {msg}\")\n                \n        elif result.status == QueryStatus.WAF:\n            if self.print_all:\n                print(Style.BRIGHT + Fore.WHITE + \"[\" +\n                      Fore.RED + \"-\" +\n                      Fore.WHITE + \"]\" +\n                      Fore.GREEN + f\" {self.result.site_name}:\" +\n                      Fore.RED + \" Blocked by bot detection\" +\n                      Fore.YELLOW + \" (proxy may help)\")\n\n        else:\n            # It should be impossible to ever get here...\n            raise ValueError(\n                f\"Unknown Query Status '{result.status}' for site '{self.result.site_name}'\"\n            )\n\n        return\n\n    def finish(self, message=\"The processing has been finished.\"):\n        \"\"\"Notify Start.\n        Will print the last line to the standard output.\n        Keyword Arguments:\n        self                   -- This object.\n        message                -- The 2 last phrases.\n        Return Value:\n        Nothing.\n        \"\"\"\n        NumberOfResults = self.countResults() - 1\n\n        print(Style.BRIGHT + Fore.GREEN + \"[\" +\n              Fore.YELLOW + \"*\" +\n              Fore.GREEN + \"] Search completed with\" +\n              Fore.WHITE + f\" {NumberOfResults} \" +\n              Fore.GREEN + \"results\" + Style.RESET_ALL\n              )\n\n    def __str__(self):\n        \"\"\"Convert Object To String.\n\n        Keyword Arguments:\n        self                   -- This object.\n\n        Return Value:\n        Nicely formatted string to get information about this object.\n        \"\"\"\n        return str(self.result)\n"
  },
  {
    "path": "sherlock_project/py.typed",
    "content": ""
  },
  {
    "path": "sherlock_project/resources/data.json",
    "content": "{\n  \"$schema\": \"data.schema.json\",\n  \"1337x\": {\n    \"errorMsg\": [\n      \"<title>Error something went wrong.</title>\",\n      \"<head><title>404 Not Found</title></head>\"\n    ],\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[A-Za-z0-9]{4,12}$\",\n    \"url\": \"https://www.1337x.to/user/{}/\",\n    \"urlMain\": \"https://www.1337x.to/\",\n    \"username_claimed\": \"FitGirl\"\n  },\n  \"2Dimensions\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://2Dimensions.com/a/{}\",\n    \"urlMain\": \"https://2Dimensions.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"7Cups\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.7cups.com/@{}\",\n    \"urlMain\": \"https://www.7cups.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"9GAG\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.9gag.com/u/{}\",\n    \"urlMain\": \"https://www.9gag.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"APClips\": {\n    \"errorMsg\": \"Amateur Porn Content Creators\",\n    \"errorType\": \"message\",\n    \"isNSFW\": true,\n    \"url\": \"https://apclips.com/{}\",\n    \"urlMain\": \"https://apclips.com/\",\n    \"username_claimed\": \"onlybbyraq\"\n  },\n  \"About.me\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://about.me/{}\",\n    \"urlMain\": \"https://about.me/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Academia.edu\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[^.]*$\",\n    \"url\": \"https://independent.academia.edu/{}\",\n    \"urlMain\": \"https://www.academia.edu/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"AdmireMe.Vip\": {\n    \"errorMsg\": \"Page Not Found\",\n    \"errorType\": \"message\",\n    \"isNSFW\": true,\n    \"url\": \"https://admireme.vip/{}\",\n    \"urlMain\": \"https://admireme.vip/\",\n    \"username_claimed\": \"DemiDevil\"\n  },\n  \"Airbit\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://airbit.com/{}\",\n    \"urlMain\": \"https://airbit.com/\",\n    \"username_claimed\": \"airbit\"\n  },\n  \"Airliners\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.airliners.net/user/{}/profile/photos\",\n    \"urlMain\": \"https://www.airliners.net/\",\n    \"username_claimed\": \"yushinlin\"\n  },\n  \"All Things Worn\": {\n    \"errorMsg\": \"Sell Used Panties\",\n    \"errorType\": \"message\",\n    \"isNSFW\": true,\n    \"url\": \"https://www.allthingsworn.com/profile/{}\",\n    \"urlMain\": \"https://www.allthingsworn.com\",\n    \"username_claimed\": \"pink\"\n  },\n  \"AllMyLinks\": {\n    \"errorMsg\": \"Page not found\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[a-z0-9][a-z0-9-]{2,32}$\",\n    \"url\": \"https://allmylinks.com/{}\",\n    \"urlMain\": \"https://allmylinks.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"AniWorld\": {\n    \"errorMsg\": \"Dieses Profil ist nicht verf\\u00fcgbar\",\n    \"errorType\": \"message\",\n    \"url\": \"https://aniworld.to/user/profil/{}\",\n    \"urlMain\": \"https://aniworld.to/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Anilist\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[A-Za-z0-9]{2,20}$\",\n    \"request_method\": \"POST\",\n    \"request_payload\": {\n      \"query\": \"query($name:String){User(name:$name){id}}\",\n      \"variables\": {\n        \"name\": \"{}\"\n      }\n    },\n    \"url\": \"https://anilist.co/user/{}/\",\n    \"urlMain\": \"https://anilist.co/\",\n    \"urlProbe\": \"https://graphql.anilist.co/\",\n    \"username_claimed\": \"Josh\"\n  },\n  \"Apple Developer\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://developer.apple.com/forums/profile/{}\",\n    \"urlMain\": \"https://developer.apple.com\",\n    \"username_claimed\": \"lio24d\"\n  },\n  \"Apple Discussions\": {\n    \"errorMsg\": \"Looking for something in Apple Support Communities?\",\n    \"errorType\": \"message\",\n    \"url\": \"https://discussions.apple.com/profile/{}\",\n    \"urlMain\": \"https://discussions.apple.com\",\n    \"username_claimed\": \"jason\"\n  },\n  \"Aparat\": {\n    \"errorType\": \"status_code\",\n    \"request_method\": \"GET\",\n    \"url\": \"https://www.aparat.com/{}/\",\n    \"urlMain\": \"https://www.aparat.com/\",\n    \"urlProbe\": \"https://www.aparat.com/api/fa/v1/user/user/information/username/{}\",\n    \"username_claimed\": \"jadi\"\n  },\n  \"Archive of Our Own\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[^.]*?$\",\n    \"url\": \"https://archiveofourown.org/users/{}\",\n    \"urlMain\": \"https://archiveofourown.org/\",\n    \"username_claimed\": \"test\"\n  },\n  \"Archive.org\": {\n    \"__comment__\": \"'The resource could not be found' relates to archive downtime\",\n    \"errorMsg\": [\n      \"could not fetch an account with user item identifier\",\n      \"The resource could not be found\",\n      \"Internet Archive services are temporarily offline\"\n    ],\n    \"errorType\": \"message\",\n    \"url\": \"https://archive.org/details/@{}\",\n    \"urlMain\": \"https://archive.org\",\n    \"urlProbe\": \"https://archive.org/details/@{}?noscript=true\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Arduino Forum\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://forum.arduino.cc/u/{}/summary\",\n    \"urlMain\": \"https://forum.arduino.cc/\",\n    \"username_claimed\": \"system\"\n  },\n  \"ArtStation\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.artstation.com/{}\",\n    \"urlMain\": \"https://www.artstation.com/\",\n    \"username_claimed\": \"Blue\"\n  },\n  \"Asciinema\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://asciinema.org/~{}\",\n    \"urlMain\": \"https://asciinema.org\",\n    \"username_claimed\": \"red\"\n  },\n  \"Ask Fedora\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://ask.fedoraproject.org/u/{}\",\n    \"urlMain\": \"https://ask.fedoraproject.org/\",\n    \"username_claimed\": \"red\"\n  },\n  \"Atcoder\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://atcoder.jp/users/{}\",\n    \"urlMain\": \"https://atcoder.jp/\",\n    \"username_claimed\": \"ksun48\"\n  },\n  \"Vjudge\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://VJudge.net/user/{}\",\n    \"urlMain\": \"https://VJudge.net/\",\n    \"username_claimed\": \"tokitsukaze\"\n  },\n  \"Audiojungle\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z0-9_]+$\",\n    \"url\": \"https://audiojungle.net/user/{}\",\n    \"urlMain\": \"https://audiojungle.net/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Autofrage\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.autofrage.net/nutzer/{}\",\n    \"urlMain\": \"https://www.autofrage.net/\",\n    \"username_claimed\": \"autofrage\"\n  },\n  \"Avizo\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://www.avizo.cz/\",\n    \"url\": \"https://www.avizo.cz/{}/\",\n    \"urlMain\": \"https://www.avizo.cz/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"AWS Skills Profile\": {\n    \"errorType\": \"message\",\n    \"errorMsg\": \"shareProfileAccepted\\\":false\",\n    \"url\": \"https://skillsprofile.skillbuilder.aws/user/{}/\",\n    \"urlMain\": \"https://skillsprofile.skillbuilder.aws\",\n    \"username_claimed\": \"mayank04pant\"\n  },\n  \"BOOTH\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://booth.pm/\",\n    \"regexCheck\": \"^[\\\\w@-]+?$\",\n    \"url\": \"https://{}.booth.pm/\",\n    \"urlMain\": \"https://booth.pm/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Bandcamp\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.bandcamp.com/{}\",\n    \"urlMain\": \"https://www.bandcamp.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Bazar.cz\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://www.bazar.cz/error404.aspx\",\n    \"url\": \"https://www.bazar.cz/{}/\",\n    \"urlMain\": \"https://www.bazar.cz/\",\n    \"username_claimed\": \"pianina\"\n  },\n  \"Behance\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.behance.net/{}\",\n    \"urlMain\": \"https://www.behance.net/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Bezuzyteczna\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://bezuzyteczna.pl/uzytkownicy/{}\",\n    \"urlMain\": \"https://bezuzyteczna.pl\",\n    \"username_claimed\": \"Jackson\"\n  },\n  \"BiggerPockets\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.biggerpockets.com/users/{}\",\n    \"urlMain\": \"https://www.biggerpockets.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"BioHacking\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://forum.dangerousthings.com/u/{}\",\n    \"urlMain\": \"https://forum.dangerousthings.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"BitBucket\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z0-9-_]{1,30}$\",\n    \"url\": \"https://bitbucket.org/{}/\",\n    \"urlMain\": \"https://bitbucket.org/\",\n    \"username_claimed\": \"white\"\n  },\n  \"Bitwarden Forum\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^(?![.-])[a-zA-Z0-9_.-]{3,20}$\",\n    \"url\": \"https://community.bitwarden.com/u/{}/summary\",\n    \"urlMain\": \"https://bitwarden.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Blipfoto\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.blipfoto.com/{}\",\n    \"urlMain\": \"https://www.blipfoto.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Blitz Tactics\": {\n    \"errorMsg\": \"That page doesn't exist\",\n    \"errorType\": \"message\",\n    \"url\": \"https://blitztactics.com/{}\",\n    \"urlMain\": \"https://blitztactics.com/\",\n    \"username_claimed\": \"Lance5500\"\n  },\n  \"Blogger\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z][a-zA-Z0-9_-]*$\",\n    \"url\": \"https://{}.blogspot.com\",\n    \"urlMain\": \"https://www.blogger.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Bluesky\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://bsky.app/profile/{}.bsky.social\",\n    \"urlProbe\": \"https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor={}.bsky.social\",\n    \"urlMain\": \"https://bsky.app/\",\n    \"username_claimed\": \"mcuban\"\n  },\n  \"BongaCams\": {\n    \"errorType\": \"status_code\",\n    \"isNSFW\": true,\n    \"url\": \"https://pt.bongacams.com/profile/{}\",\n    \"urlMain\": \"https://pt.bongacams.com\",\n    \"username_claimed\": \"asuna-black\"\n  },\n  \"Bookcrossing\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.bookcrossing.com/mybookshelf/{}/\",\n    \"urlMain\": \"https://www.bookcrossing.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"BoardGameGeek\": {\n    \"errorMsg\": \"\\\"isValid\\\":true\",\n    \"errorType\": \"message\",\n    \"url\": \"https://boardgamegeek.com/user/{}\",\n    \"urlMain\": \"https://boardgamegeek.com/\",\n    \"urlProbe\": \"https://api.geekdo.com/api/accounts/validate/username?username={}\",\n    \"username_claimed\": \"blue\"\n  },\n  \"BraveCommunity\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://community.brave.com/u/{}/\",\n    \"urlMain\": \"https://community.brave.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"BreachSta.rs Forum\": {\n    \"errorMsg\": \"<title>Error - BreachStars</title>\",\n    \"errorType\": \"message\",\n    \"url\": \"https://breachsta.rs/profile/{}\",\n    \"urlMain\": \"https://breachsta.rs/\",\n    \"username_claimed\": \"Sleepybubble\"\n  },\n  \"BugCrowd\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://bugcrowd.com/{}\",\n    \"urlMain\": \"https://bugcrowd.com/\",\n    \"username_claimed\": \"ppfeister\"\n  },\n  \"BuyMeACoffee\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"[a-zA-Z0-9]{3,15}\",\n    \"url\": \"https://buymeacoff.ee/{}\",\n    \"urlMain\": \"https://www.buymeacoffee.com/\",\n    \"urlProbe\": \"https://www.buymeacoffee.com/{}\",\n    \"username_claimed\": \"red\"\n  },\n  \"BuzzFeed\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://buzzfeed.com/{}\",\n    \"urlMain\": \"https://buzzfeed.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Cfx.re Forum\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://forum.cfx.re/u/{}/summary\",\n    \"urlMain\": \"https://forum.cfx.re\",\n    \"username_claimed\": \"hightowerlssd\"\n  },\n  \"CGTrader\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[^.]*?$\",\n    \"url\": \"https://www.cgtrader.com/{}\",\n    \"urlMain\": \"https://www.cgtrader.com\",\n    \"username_claimed\": \"blue\"\n  },\n  \"CNET\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-z].*$\",\n    \"url\": \"https://www.cnet.com/profiles/{}/\",\n    \"urlMain\": \"https://www.cnet.com/\",\n    \"username_claimed\": \"melliott\"\n  },\n  \"CSSBattle\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://cssbattle.dev/player/{}\",\n    \"urlMain\": \"https://cssbattle.dev\",\n    \"username_claimed\": \"beo\"\n  },\n  \"CTAN\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://ctan.org/author/{}\",\n    \"urlMain\": \"https://ctan.org/\",\n    \"username_claimed\": \"briggs\"\n  },\n  \"Caddy Community\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://caddy.community/u/{}/summary\",\n    \"urlMain\": \"https://caddy.community/\",\n    \"username_claimed\": \"taako_magnusen\"\n  },\n  \"Car Talk Community\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://community.cartalk.com/u/{}/summary\",\n    \"urlMain\": \"https://community.cartalk.com/\",\n    \"username_claimed\": \"always_fixing\"\n  },\n  \"Carbonmade\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://carbonmade.com/fourohfour?domain={}.carbonmade.com\",\n    \"regexCheck\": \"^[\\\\w@-]+?$\",\n    \"url\": \"https://{}.carbonmade.com\",\n    \"urlMain\": \"https://carbonmade.com/\",\n    \"username_claimed\": \"jenny\"\n  },\n  \"Career.habr\": {\n    \"errorMsg\": \"<h1>\\u041e\\u0448\\u0438\\u0431\\u043a\\u0430 404</h1>\",\n    \"errorType\": \"message\",\n    \"url\": \"https://career.habr.com/{}\",\n    \"urlMain\": \"https://career.habr.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"CashApp\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://cash.app/${}\",\n    \"urlMain\": \"https://cash.app\",\n    \"username_claimed\": \"hotdiggitydog\"\n  },\n  \"Championat\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.championat.com/user/{}\",\n    \"urlMain\": \"https://www.championat.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Chaos\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://chaos.social/@{}\",\n    \"urlMain\": \"https://chaos.social/\",\n    \"username_claimed\": \"ordnung\"\n  },\n  \"Chatujme.cz\": {\n    \"errorMsg\": \"Neexistujic\\u00ed profil\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[a-zA-Z][a-zA-Z1-9_-]*$\",\n    \"url\": \"https://profil.chatujme.cz/{}\",\n    \"urlMain\": \"https://chatujme.cz/\",\n    \"username_claimed\": \"david\"\n  },\n  \"ChaturBate\": {\n    \"errorType\": \"status_code\",\n    \"isNSFW\": true,\n    \"url\": \"https://chaturbate.com/{}\",\n    \"urlMain\": \"https://chaturbate.com\",\n    \"username_claimed\": \"cute18cute\"\n  },\n  \"Chess\": {\n    \"errorMsg\": \"Username is valid\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[a-zA-Z0-9_]{3,25}$\",\n    \"url\": \"https://www.chess.com/member/{}\",\n    \"urlMain\": \"https://www.chess.com/\",\n    \"urlProbe\": \"https://www.chess.com/callback/user/valid?username={}\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Choice Community\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://choice.community/u/{}/summary\",\n    \"urlMain\": \"https://choice.community/\",\n    \"username_claimed\": \"gordon\"\n  },\n  \"Clapper\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://clapperapp.com/{}\",\n    \"urlMain\": \"https://clapperapp.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"CloudflareCommunity\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://community.cloudflare.com/u/{}\",\n    \"urlMain\": \"https://community.cloudflare.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Clozemaster\": {\n    \"errorMsg\": \"Oh no! Player not found.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.clozemaster.com/players/{}\",\n    \"urlMain\": \"https://www.clozemaster.com\",\n    \"username_claimed\": \"green\"\n  },\n  \"Clubhouse\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.clubhouse.com/@{}\",\n    \"urlMain\": \"https://www.clubhouse.com\",\n    \"username_claimed\": \"waniathar\"\n  },\n  \"Code Snippet Wiki\": {\n    \"errorMsg\": \"This user has not filled out their profile page yet\",\n    \"errorType\": \"message\",\n    \"url\": \"https://codesnippets.fandom.com/wiki/User:{}\",\n    \"urlMain\": \"https://codesnippets.fandom.com\",\n    \"username_claimed\": \"bob\"\n  },\n  \"Codeberg\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://codeberg.org/{}\",\n    \"urlMain\": \"https://codeberg.org/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Codecademy\": {\n    \"errorMsg\": \"This profile could not be found\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.codecademy.com/profiles/{}\",\n    \"urlMain\": \"https://www.codecademy.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Codechef\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://www.codechef.com/\",\n    \"url\": \"https://www.codechef.com/users/{}\",\n    \"urlMain\": \"https://www.codechef.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Codeforces\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://codeforces.com/profile/{}\",\n    \"urlMain\": \"https://codeforces.com/\",\n    \"urlProbe\": \"https://codeforces.com/api/user.info?handles={}\",\n    \"username_claimed\": \"tourist\"\n  },\n  \"Codepen\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://codepen.io/{}\",\n    \"urlMain\": \"https://codepen.io/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Coders Rank\": {\n    \"errorMsg\": \"not a registered member\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[a-zA-Z0-9](?:[a-zA-Z0-9]|-(?=[a-zA-Z0-9])){0,38}$\",\n    \"url\": \"https://profile.codersrank.io/user/{}/\",\n    \"urlMain\": \"https://codersrank.io/\",\n    \"username_claimed\": \"rootkit7628\"\n  },\n  \"Coderwall\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://coderwall.com/{}\",\n    \"urlMain\": \"https://coderwall.com\",\n    \"username_claimed\": \"hacker\"\n  },\n  \"CodeSandbox\": {\n    \"errorType\": \"message\",\n    \"errorMsg\": \"Could not find user with username\",\n    \"regexCheck\": \"^[a-zA-Z0-9_-]{3,30}$\",\n    \"url\": \"https://codesandbox.io/u/{}\",\n    \"urlProbe\": \"https://codesandbox.io/api/v1/users/{}\",\n    \"urlMain\": \"https://codesandbox.io\",\n    \"username_claimed\": \"icyjoseph\"\n  },\n  \"Codewars\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.codewars.com/users/{}\",\n    \"urlMain\": \"https://www.codewars.com\",\n    \"username_claimed\": \"example\"\n  },\n  \"Codolio\": {\n    \"errorType\": \"message\",\n    \"errorMsg\": \"<title>Page Not Found | Codolio</title>\",\n    \"url\": \"https://codolio.com/profile/{}\",\n    \"urlMain\": \"https://codolio.com/\",\n    \"username_claimed\": \"testuser\",\n    \"regexCheck\": \"^[a-zA-Z0-9_-]{3,30}$\"\n  },\n  \"Coinvote\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://coinvote.cc/profile/{}\",\n    \"urlMain\": \"https://coinvote.cc/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"ColourLovers\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.colourlovers.com/lover/{}\",\n    \"urlMain\": \"https://www.colourlovers.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Contently\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://contently.com\",\n    \"regexCheck\": \"^[a-zA-Z][a-zA-Z0-9_-]*$\",\n    \"url\": \"https://{}.contently.com/\",\n    \"urlMain\": \"https://contently.com/\",\n    \"username_claimed\": \"jordanteicher\"\n  },\n  \"Coroflot\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.coroflot.com/{}\",\n    \"urlMain\": \"https://coroflot.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Cplusplus\": {\n    \"errorType\": \"message\",\n    \"errorMsg\": \"<title>404 Page Not Found</title>\",\n    \"url\": \"https://cplusplus.com/user/{}\",\n    \"urlMain\": \"https://cplusplus.com\",\n    \"username_claimed\": \"mbozzi\"\n  },\n  \"Cracked\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://www.cracked.com/\",\n    \"url\": \"https://www.cracked.com/members/{}/\",\n    \"urlMain\": \"https://www.cracked.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Cracked Forum\": {\n    \"errorMsg\": \"The member you specified is either invalid or doesn't exist\",\n    \"errorType\": \"message\",\n    \"url\": \"https://cracked.sh/{}\",\n    \"urlMain\": \"https://cracked.sh/\",\n    \"username_claimed\": \"Blue\"\n  },\n  \"Credly\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.credly.com/users/{}\",\n    \"urlMain\": \"https://www.credly.com/\",\n    \"username_claimed\": \"credly\"\n  },\n  \"Crevado\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[\\\\w@-]+?$\",\n    \"url\": \"https://{}.crevado.com\",\n    \"urlMain\": \"https://crevado.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Crowdin\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z0-9._-]{2,255}$\",\n    \"url\": \"https://crowdin.com/profile/{}\",\n    \"urlMain\": \"https://crowdin.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"CryptoHack\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://cryptohack.org/\",\n    \"url\": \"https://cryptohack.org/user/{}/\",\n    \"urlMain\": \"https://cryptohack.org/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Cryptomator Forum\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://community.cryptomator.org/u/{}\",\n    \"urlMain\": \"https://community.cryptomator.org/\",\n    \"username_claimed\": \"michael\"\n  },\n  \"Cults3D\": {\n    \"errorMsg\": \"Oh dear, this page is not working!\",\n    \"errorType\": \"message\",\n    \"url\": \"https://cults3d.com/en/users/{}/creations\",\n    \"urlMain\": \"https://cults3d.com/en\",\n    \"username_claimed\": \"brown\"\n  },\n  \"CyberDefenders\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[^\\\\/:*?\\\"<>|@]{3,50}$\",\n    \"request_method\": \"GET\",\n    \"url\": \"https://cyberdefenders.org/p/{}\",\n    \"urlMain\": \"https://cyberdefenders.org/\",\n    \"username_claimed\": \"mlohn\"\n  },\n  \"DEV Community\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z][a-zA-Z0-9_-]*$\",\n    \"url\": \"https://dev.to/{}\",\n    \"urlMain\": \"https://dev.to/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"DMOJ\": {\n    \"errorMsg\": \"No such user\",\n    \"errorType\": \"message\",\n    \"url\": \"https://dmoj.ca/user/{}\",\n    \"urlMain\": \"https://dmoj.ca/\",\n    \"username_claimed\": \"junferno\"\n  },\n  \"DailyMotion\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.dailymotion.com/{}\",\n    \"urlMain\": \"https://www.dailymotion.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"dcinside\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://gallog.dcinside.com/{}\",\n    \"urlMain\": \"https://www.dcinside.com/\",\n    \"username_claimed\": \"anrbrb\"\n  },\n  \"Dealabs\": {\n    \"errorMsg\": \"La page que vous essayez\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"[a-z0-9]{4,16}\",\n    \"url\": \"https://www.dealabs.com/profile/{}\",\n    \"urlMain\": \"https://www.dealabs.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"DeviantArt\": {\n    \"errorType\": \"message\",\n    \"errorMsg\": \"Llama Not Found\",\n    \"regexCheck\": \"^[a-zA-Z][a-zA-Z0-9_-]*$\",\n    \"url\": \"https://www.deviantart.com/{}\",\n    \"urlMain\": \"https://www.deviantart.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"DigitalSpy\": {\n    \"errorMsg\": \"The page you were looking for could not be found.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://forums.digitalspy.com/profile/{}\",\n    \"urlMain\": \"https://forums.digitalspy.com/\",\n    \"username_claimed\": \"blue\",\n    \"regexCheck\": \"^\\\\w{3,20}$\"\n  },\n  \"Discogs\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.discogs.com/user/{}\",\n    \"urlMain\": \"https://www.discogs.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Discord\": {\n    \"errorType\": \"message\",\n    \"url\": \"https://discord.com\",\n    \"urlMain\": \"https://discord.com/\",\n    \"urlProbe\": \"https://discord.com/api/v9/unique-username/username-attempt-unauthed\",\n    \"errorMsg\": [\"{\\\"taken\\\":false}\", \"The resource is being rate limited\"],\n    \"request_method\": \"POST\",\n    \"request_payload\": {\n      \"username\": \"{}\"\n    },\n    \"headers\": {\n      \"Content-Type\": \"application/json\"\n    },\n    \"username_claimed\": \"blue\"\n  },\n  \"Discord.bio\": {\n    \"errorType\": \"message\",\n    \"errorMsg\": \"<title>Server Error (500)</title>\",\n    \"url\": \"https://discords.com/api-v2/bio/details/{}\",\n    \"urlMain\": \"https://discord.bio/\",\n    \"username_claimed\": \"robert\"\n  },\n  \"Discuss.Elastic.co\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://discuss.elastic.co/u/{}\",\n    \"urlMain\": \"https://discuss.elastic.co/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Diskusjon.no\": {\n    \"errorMsg\": \"{\\\"result\\\":\\\"ok\\\"}\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[a-zA-Z0-9_.-]{3,40}$\",\n    \"urlProbe\": \"https://www.diskusjon.no/?app=core&module=system&controller=ajax&do=usernameExists&input={}\",\n    \"url\": \"https://www.diskusjon.no\",\n    \"urlMain\": \"https://www.diskusjon.no\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Disqus\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://disqus.com/{}\",\n    \"urlMain\": \"https://disqus.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Docker Hub\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://hub.docker.com/u/{}/\",\n    \"urlMain\": \"https://hub.docker.com/\",\n    \"urlProbe\": \"https://hub.docker.com/v2/users/{}/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Dribbble\": {\n    \"errorMsg\": \"Whoops, that page is gone.\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[a-zA-Z][a-zA-Z0-9_-]*$\",\n    \"url\": \"https://dribbble.com/{}\",\n    \"urlMain\": \"https://dribbble.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Duolingo\": {\n    \"errorMsg\": \"{\\\"users\\\":[]}\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.duolingo.com/profile/{}\",\n    \"urlMain\": \"https://duolingo.com/\",\n    \"urlProbe\": \"https://www.duolingo.com/2017-06-30/users?username={}\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Eintracht Frankfurt Forum\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[^.]*?$\",\n    \"url\": \"https://community.eintracht.de/fans/{}\",\n    \"urlMain\": \"https://community.eintracht.de/\",\n    \"username_claimed\": \"mmammu\"\n  },\n  \"Empretienda AR\": {\n    \"__comment__\": \"Note that Error Connecting responses may be indicative of unclaimed handles\",\n    \"errorType\": \"status_code\",\n    \"url\": \"https://{}.empretienda.com.ar\",\n    \"urlMain\": \"https://empretienda.com\",\n    \"username_claimed\": \"camalote\"\n  },\n  \"Envato Forum\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://forums.envato.com/u/{}\",\n    \"urlMain\": \"https://forums.envato.com/\",\n    \"username_claimed\": \"enabled\"\n  },\n  \"Erome\": {\n    \"errorType\": \"status_code\",\n    \"isNSFW\": true,\n    \"url\": \"https://www.erome.com/{}\",\n    \"urlMain\": \"https://www.erome.com/\",\n    \"username_claimed\": \"bob\"\n  },\n  \"Exposure\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z0-9-]{1,63}$\",\n    \"url\": \"https://{}.exposure.co/\",\n    \"urlMain\": \"https://exposure.co/\",\n    \"username_claimed\": \"jonasjacobsson\"\n  },\n  \"exophase\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.exophase.com/user/{}/\",\n    \"urlMain\": \"https://www.exophase.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"EyeEm\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.eyeem.com/u/{}\",\n    \"urlMain\": \"https://www.eyeem.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"F3.cool\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://f3.cool/{}/\",\n    \"urlMain\": \"https://f3.cool/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Fameswap\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://fameswap.com/user/{}\",\n    \"urlMain\": \"https://fameswap.com/\",\n    \"username_claimed\": \"fameswap\"\n  },\n  \"Fandom\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.fandom.com/u/{}\",\n    \"urlMain\": \"https://www.fandom.com/\",\n    \"username_claimed\": \"Jungypoo\"\n  },\n  \"Fanpop\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://www.fanpop.com/\",\n    \"url\": \"https://www.fanpop.com/fans/{}\",\n    \"urlMain\": \"https://www.fanpop.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Finanzfrage\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.finanzfrage.net/nutzer/{}\",\n    \"urlMain\": \"https://www.finanzfrage.net/\",\n    \"username_claimed\": \"finanzfrage\"\n  },\n  \"Flickr\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.flickr.com/people/{}\",\n    \"urlMain\": \"https://www.flickr.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Flightradar24\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z0-9_]{3,20}$\",\n    \"url\": \"https://my.flightradar24.com/{}\",\n    \"urlMain\": \"https://www.flightradar24.com/\",\n    \"username_claimed\": \"jebbrooks\"\n  },\n  \"Flipboard\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^([a-zA-Z0-9_]){1,15}$\",\n    \"url\": \"https://flipboard.com/@{}\",\n    \"urlMain\": \"https://flipboard.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Football\": {\n    \"errorMsg\": \"\\u041f\\u043e\\u043b\\u044c\\u0437\\u043e\\u0432\\u0430\\u0442\\u0435\\u043b\\u044c \\u0441 \\u0442\\u0430\\u043a\\u0438\\u043c \\u0438\\u043c\\u0435\\u043d\\u0435\\u043c \\u043d\\u0435 \\u043d\\u0430\\u0439\\u0434\\u0435\\u043d\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.rusfootball.info/user/{}/\",\n    \"urlMain\": \"https://www.rusfootball.info/\",\n    \"username_claimed\": \"solo87\"\n  },\n  \"FortniteTracker\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://fortnitetracker.com/profile/all/{}\",\n    \"urlMain\": \"https://fortnitetracker.com/challenges\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Forum Ophilia\": {\n    \"errorMsg\": \"that user does not exist\",\n    \"errorType\": \"message\",\n    \"isNSFW\": true,\n    \"url\": \"https://www.forumophilia.com/profile.php?mode=viewprofile&u={}\",\n    \"urlMain\": \"https://www.forumophilia.com/\",\n    \"username_claimed\": \"bob\"\n  },\n  \"Fosstodon\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z0-9_]{1,30}$\",\n    \"url\": \"https://fosstodon.org/@{}\",\n    \"urlMain\": \"https://fosstodon.org/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Framapiaf\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z0-9_]{1,30}$\",\n    \"url\": \"https://framapiaf.org/@{}\",\n    \"urlMain\": \"https://framapiaf.org\",\n    \"username_claimed\": \"pylapp\"\n  },\n  \"Freelancer\": {\n    \"errorMsg\": \"\\\"users\\\":{}\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.freelancer.com/u/{}\",\n    \"urlMain\": \"https://www.freelancer.com/\",\n    \"urlProbe\": \"https://www.freelancer.com/api/users/0.1/users?usernames%5B%5D={}&compact=true\",\n    \"username_claimed\": \"red0xff\"\n  },\n  \"Freesound\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://freesound.org/people/{}/\",\n    \"urlMain\": \"https://freesound.org/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"GNOME VCS\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://gitlab.gnome.org/{}\",\n    \"regexCheck\": \"^(?!-)[a-zA-Z0-9_.-]{2,255}(?<!\\\\.)$\",\n    \"url\": \"https://gitlab.gnome.org/{}\",\n    \"urlMain\": \"https://gitlab.gnome.org/\",\n    \"username_claimed\": \"adam\"\n  },\n  \"GaiaOnline\": {\n    \"errorMsg\": \"No user ID specified or user does not exist\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.gaiaonline.com/profiles/{}\",\n    \"urlMain\": \"https://www.gaiaonline.com/\",\n    \"username_claimed\": \"adam\"\n  },\n  \"Gamespot\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.gamespot.com/profile/{}/\",\n    \"urlMain\": \"https://www.gamespot.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"GameFAQs\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://gamefaqs.gamespot.com/community/{}\",\n    \"urlMain\": \"https://gamefaqs.gamespot.com\",\n    \"username_claimed\": \"blue\"\n  },\n  \"GeeksforGeeks\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://auth.geeksforgeeks.org/user/{}\",\n    \"urlMain\": \"https://www.geeksforgeeks.org/\",\n    \"username_claimed\": \"adam\"\n  },\n  \"Genius (Artists)\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z0-9]{5,50}$\",\n    \"url\": \"https://genius.com/artists/{}\",\n    \"urlMain\": \"https://genius.com/\",\n    \"username_claimed\": \"genius\"\n  },\n  \"Genius (Users)\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z0-9]*?$\",\n    \"url\": \"https://genius.com/{}\",\n    \"urlMain\": \"https://genius.com/\",\n    \"username_claimed\": \"genius\"\n  },\n  \"Gesundheitsfrage\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.gesundheitsfrage.net/nutzer/{}\",\n    \"urlMain\": \"https://www.gesundheitsfrage.net/\",\n    \"username_claimed\": \"gutefrage\"\n  },\n  \"GetMyUni\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.getmyuni.com/user/{}\",\n    \"urlMain\": \"https://getmyuni.com/\",\n    \"username_claimed\": \"Upneet.Grover17\"\n  },\n  \"Giant Bomb\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.giantbomb.com/profile/{}/\",\n    \"urlMain\": \"https://www.giantbomb.com/\",\n    \"username_claimed\": \"bob\"\n  },\n  \"Giphy\": {\n    \"errorType\": \"message\",\n    \"errorMsg\": \"<title> GIFs - Find &amp; Share on GIPHY</title>\",\n    \"url\": \"https://giphy.com/{}\",\n    \"urlMain\": \"https://giphy.com/\",\n    \"username_claimed\": \"red\"\n  },\n  \"GitBook\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[\\\\w@-]+?$\",\n    \"url\": \"https://{}.gitbook.io/\",\n    \"urlMain\": \"https://gitbook.com/\",\n    \"username_claimed\": \"gitbook\"\n  },\n  \"GitHub\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z0-9](?:[a-zA-Z0-9]|-(?=[a-zA-Z0-9])){0,38}$\",\n    \"url\": \"https://www.github.com/{}\",\n    \"urlMain\": \"https://www.github.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Warframe Market\": {\n    \"errorType\": \"status_code\",\n    \"request_method\": \"GET\",\n    \"url\": \"https://warframe.market/profile/{}\",\n    \"urlMain\": \"https://warframe.market/\",\n    \"urlProbe\": \"https://api.warframe.market/v2/user/{}\",\n    \"username_claimed\": \"kaiallalone\"\n  },\n  \"GitLab\": {\n    \"errorMsg\": \"[]\",\n    \"errorType\": \"message\",\n    \"url\": \"https://gitlab.com/{}\",\n    \"urlMain\": \"https://gitlab.com/\",\n    \"urlProbe\": \"https://gitlab.com/api/v4/users?username={}\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Gitea\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://gitea.com/{}\",\n    \"urlMain\": \"https://gitea.com/\",\n    \"username_claimed\": \"xorm\"\n  },\n  \"Gitee\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://gitee.com/{}\",\n    \"urlMain\": \"https://gitee.com/\",\n    \"username_claimed\": \"wizzer\"\n  },\n  \"GoodReads\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.goodreads.com/{}\",\n    \"urlMain\": \"https://www.goodreads.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Google Play\": {\n    \"errorMsg\": \"the requested URL was not found on this server\",\n    \"errorType\": \"message\",\n    \"url\": \"https://play.google.com/store/apps/developer?id={}\",\n    \"urlMain\": \"https://play.google.com\",\n    \"username_claimed\": \"GitHub\"\n  },\n  \"Gradle\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^(?!-)[a-zA-Z0-9-]{3,}(?<!-)$\",\n    \"url\": \"https://plugins.gradle.org/u/{}\",\n    \"urlMain\": \"https://gradle.org/\",\n    \"username_claimed\": \"jetbrains\"\n  },\n  \"Grailed\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://www.grailed.com/{}\",\n    \"url\": \"https://www.grailed.com/{}\",\n    \"urlMain\": \"https://www.grailed.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Gravatar\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^((?!\\\\.).)*$\",\n    \"url\": \"http://en.gravatar.com/{}\",\n    \"urlMain\": \"http://en.gravatar.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Gumroad\": {\n    \"errorMsg\": \"Page not found (404) - Gumroad\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[^.]*?$\",\n    \"url\": \"https://www.gumroad.com/{}\",\n    \"urlMain\": \"https://www.gumroad.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Gutefrage\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.gutefrage.net/nutzer/{}\",\n    \"urlMain\": \"https://www.gutefrage.net/\",\n    \"username_claimed\": \"gutefrage\"\n  },\n  \"HackTheBox\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://forum.hackthebox.com/u/{}\",\n    \"urlMain\": \"https://forum.hackthebox.com/\",\n    \"username_claimed\": \"angar\"\n  },\n  \"Hackaday\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://hackaday.io/{}\",\n    \"urlMain\": \"https://hackaday.io/\",\n    \"username_claimed\": \"adam\"\n  },\n  \"HackenProof (Hackers)\": {\n    \"errorMsg\": \"Page not found\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[\\\\w-]{,34}$\",\n    \"url\": \"https://hackenproof.com/hackers/{}\",\n    \"urlMain\": \"https://hackenproof.com/\",\n    \"username_claimed\": \"blazezaria\"\n  },\n  \"HackerEarth\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://hackerearth.com/@{}\",\n    \"urlMain\": \"https://hackerearth.com/\",\n    \"username_claimed\": \"naveennamani877\"\n  },\n  \"HackerNews\": {\n    \"__comment__\": \"First errMsg invalid, second errMsg rate limited. Not ideal. Adjust for better rate limit filtering.\",\n    \"errorMsg\": [\"No such user.\", \"Sorry.\"],\n    \"errorType\": \"message\",\n    \"url\": \"https://news.ycombinator.com/user?id={}\",\n    \"urlMain\": \"https://news.ycombinator.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"HackerOne\": {\n    \"errorMsg\": \"Page not found\",\n    \"errorType\": \"message\",\n    \"url\": \"https://hackerone.com/{}\",\n    \"urlMain\": \"https://hackerone.com/\",\n    \"username_claimed\": \"stok\"\n  },\n  \"HackerRank\": {\n    \"errorMsg\": \"Something went wrong\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[^.]*?$\",\n    \"url\": \"https://hackerrank.com/{}\",\n    \"urlMain\": \"https://hackerrank.com/\",\n    \"username_claimed\": \"satznova\"\n  },\n  \"HackerSploit\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://forum.hackersploit.org/u/{}\",\n    \"urlMain\": \"https://forum.hackersploit.org/\",\n    \"username_claimed\": \"hackersploit\"\n  },\n  \"HackMD\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://hackmd.io/@{}\",\n    \"urlMain\": \"https://hackmd.io/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Harvard Scholar\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://scholar.harvard.edu/{}\",\n    \"urlMain\": \"https://scholar.harvard.edu/\",\n    \"username_claimed\": \"ousmanekane\"\n  },\n  \"Hashnode\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://hashnode.com/@{}\",\n    \"urlMain\": \"https://hashnode.com\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Heavy-R\": {\n    \"errorMsg\": \"Channel not found\",\n    \"errorType\": \"message\",\n    \"isNSFW\": true,\n    \"url\": \"https://www.heavy-r.com/user/{}\",\n    \"urlMain\": \"https://www.heavy-r.com/\",\n    \"username_claimed\": \"kilroy222\"\n  },\n  \"Hive Blog\": {\n    \"errorMsg\": \"<title>User Not Found - Hive</title>\",\n    \"errorType\": \"message\",\n    \"url\": \"https://hive.blog/@{}\",\n    \"urlMain\": \"https://hive.blog/\",\n    \"username_claimed\": \"mango-juice\"\n  },\n  \"Holopin\": {\n    \"errorMsg\": \"true\",\n    \"errorType\": \"message\",\n    \"request_method\": \"POST\",\n    \"request_payload\": {\n      \"username\": \"{}\"\n    },\n    \"url\": \"https://holopin.io/@{}\",\n    \"urlMain\": \"https://holopin.io\",\n    \"urlProbe\": \"https://www.holopin.io/api/auth/username\",\n    \"username_claimed\": \"red\"\n  },\n  \"Houzz\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://houzz.com/user/{}\",\n    \"urlMain\": \"https://houzz.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"HubPages\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://hubpages.com/@{}\",\n    \"urlMain\": \"https://hubpages.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Hubski\": {\n    \"errorMsg\": \"No such user\",\n    \"errorType\": \"message\",\n    \"url\": \"https://hubski.com/user/{}\",\n    \"urlMain\": \"https://hubski.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"HudsonRock\": {\n    \"errorMsg\": \"This username is not associated\",\n    \"errorType\": \"message\",\n    \"url\": \"https://cavalier.hudsonrock.com/api/json/v2/osint-tools/search-by-username?username={}\",\n    \"urlMain\": \"https://hudsonrock.com\",\n    \"username_claimed\": \"testadmin\"\n  },\n  \"Hugging Face\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://huggingface.co/{}\",\n    \"urlMain\": \"https://huggingface.co/\",\n    \"username_claimed\": \"Pasanlaksitha\"\n  },\n  \"IFTTT\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[A-Za-z0-9]{3,35}$\",\n    \"url\": \"https://www.ifttt.com/p/{}\",\n    \"urlMain\": \"https://www.ifttt.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Ifunny\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://ifunny.co/user/{}\",\n    \"urlMain\": \"https://ifunny.co/\",\n    \"username_claimed\": \"agua\"\n  },\n  \"IRC-Galleria\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://irc-galleria.net/users/search?username={}\",\n    \"url\": \"https://irc-galleria.net/user/{}\",\n    \"urlMain\": \"https://irc-galleria.net/\",\n    \"username_claimed\": \"appas\"\n  },\n  \"Icons8 Community\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://community.icons8.com/u/{}/summary\",\n    \"urlMain\": \"https://community.icons8.com/\",\n    \"username_claimed\": \"thefourCraft\"\n  },\n  \"Image Fap\": {\n    \"errorMsg\": \"Not found\",\n    \"errorType\": \"message\",\n    \"isNSFW\": true,\n    \"url\": \"https://www.imagefap.com/profile/{}\",\n    \"urlMain\": \"https://www.imagefap.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"ImgUp.cz\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://imgup.cz/{}\",\n    \"urlMain\": \"https://imgup.cz/\",\n    \"username_claimed\": \"adam\"\n  },\n  \"Imgur\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://imgur.com/user/{}\",\n    \"urlMain\": \"https://imgur.com/\",\n    \"urlProbe\": \"https://api.imgur.com/account/v1/accounts/{}?client_id=546c25a59c58ad7\",\n    \"username_claimed\": \"blue\"\n  },\n  \"imood\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.imood.com/users/{}\",\n    \"urlMain\": \"https://www.imood.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Instagram\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://instagram.com/{}\",\n    \"urlMain\": \"https://instagram.com/\",\n    \"urlProbe\": \"https://imginn.com/{}\",\n    \"username_claimed\": \"instagram\"\n  },\n  \"Instapaper\": {\n    \"errorType\": \"status_code\",\n    \"request_method\": \"GET\",\n    \"url\": \"https://www.instapaper.com/p/{}\",\n    \"urlMain\": \"https://www.instapaper.com/\",\n    \"username_claimed\": \"john\"\n  },\n  \"Instructables\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.instructables.com/member/{}\",\n    \"urlMain\": \"https://www.instructables.com/\",\n    \"urlProbe\": \"https://www.instructables.com/json-api/showAuthorExists?screenName={}\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Intigriti\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"[a-z0-9_]{1,25}\",\n    \"request_method\": \"GET\",\n    \"url\": \"https://app.intigriti.com/profile/{}\",\n    \"urlMain\": \"https://app.intigriti.com\",\n    \"urlProbe\": \"https://api.intigriti.com/user/public/profile/{}\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Ionic Forum\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://forum.ionicframework.com/u/{}\",\n    \"urlMain\": \"https://forum.ionicframework.com/\",\n    \"username_claimed\": \"theblue222\"\n  },\n  \"Issuu\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://issuu.com/{}\",\n    \"urlMain\": \"https://issuu.com/\",\n    \"username_claimed\": \"jenny\"\n  },\n  \"Itch.io\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[\\\\w@-]+?$\",\n    \"url\": \"https://{}.itch.io/\",\n    \"urlMain\": \"https://itch.io/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Itemfix\": {\n    \"errorMsg\": \"<title>ItemFix - Channel: </title>\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.itemfix.com/c/{}\",\n    \"urlMain\": \"https://www.itemfix.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Jellyfin Weblate\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z0-9@._-]{1,150}$\",\n    \"url\": \"https://translate.jellyfin.org/user/{}/\",\n    \"urlMain\": \"https://translate.jellyfin.org/\",\n    \"username_claimed\": \"EraYaN\"\n  },\n  \"Jimdo\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[\\\\w@-]+?$\",\n    \"url\": \"https://{}.jimdosite.com\",\n    \"urlMain\": \"https://jimdosite.com/\",\n    \"username_claimed\": \"jenny\"\n  },\n  \"Joplin Forum\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://discourse.joplinapp.org/u/{}\",\n    \"urlMain\": \"https://discourse.joplinapp.org/\",\n    \"username_claimed\": \"laurent\"\n  },\n  \"Jupyter Community Forum\": {\n    \"errorMsg\": \"Oops! That page doesn’t exist or is private.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://discourse.jupyter.org/u/{}/summary\",\n    \"urlMain\": \"https://discourse.jupyter.org\",\n    \"username_claimed\": \"choldgraf\"\n  },\n  \"Kaggle\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.kaggle.com/{}\",\n    \"urlMain\": \"https://www.kaggle.com/\",\n    \"username_claimed\": \"dansbecker\"\n  },\n  \"kaskus\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.kaskus.co.id/@{}\",\n    \"urlMain\": \"https://www.kaskus.co.id\",\n    \"urlProbe\": \"https://www.kaskus.co.id/api/users?username={}\",\n    \"request_method\": \"GET\",\n    \"username_claimed\": \"l0mbart\"\n  },\n  \"Keybase\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://keybase.io/{}\",\n    \"urlMain\": \"https://keybase.io/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Kick\": {\n    \"__comment__\": \"Cloudflare. Only viable when proxied.\",\n    \"errorType\": \"status_code\",\n    \"url\": \"https://kick.com/{}\",\n    \"urlMain\": \"https://kick.com/\",\n    \"urlProbe\": \"https://kick.com/api/v2/channels/{}\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Kik\": {\n    \"errorMsg\": \"The page you requested was not found\",\n    \"errorType\": \"message\",\n    \"url\": \"https://kik.me/{}\",\n    \"urlMain\": \"http://kik.me/\",\n    \"urlProbe\": \"https://ws2.kik.com/user/{}\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Kongregate\": {\n    \"errorType\": \"status_code\",\n    \"headers\": {\n      \"Accept\": \"text/html\"\n    },\n    \"regexCheck\": \"^[a-zA-Z][a-zA-Z0-9_-]*$\",\n    \"url\": \"https://www.kongregate.com/accounts/{}\",\n    \"urlMain\": \"https://www.kongregate.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Kvinneguiden\": {\n    \"errorMsg\": \"{\\\"result\\\":\\\"ok\\\"}\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[a-zA-Z0-9_.-]{3,18}$\",\n    \"urlProbe\": \"https://forum.kvinneguiden.no/?app=core&module=system&controller=ajax&do=usernameExists&input={}\",\n    \"url\": \"https://forum.kvinneguiden.no\",\n    \"urlMain\": \"https://forum.kvinneguiden.no\",\n    \"username_claimed\": \"blue\"\n  },\n  \"LOR\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.linux.org.ru/people/{}/profile\",\n    \"urlMain\": \"https://linux.org.ru/\",\n    \"username_claimed\": \"red\"\n  },\n  \"Laracast\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://laracasts.com/@{}\",\n    \"urlMain\": \"https://laracasts.com/\",\n    \"regexCheck\": \"^[a-zA-Z0-9_-]{3,}$\",\n    \"username_claimed\": \"user1\"\n  },\n  \"Launchpad\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://launchpad.net/~{}\",\n    \"urlMain\": \"https://launchpad.net/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"LeetCode\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://leetcode.com/{}\",\n    \"urlMain\": \"https://leetcode.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"LemmyWorld\": {\n    \"errorType\": \"message\",\n    \"errorMsg\": \"<h1>Error!</h1>\",\n    \"url\": \"https://lemmy.world/u/{}\",\n    \"urlMain\": \"https://lemmy.world\",\n    \"username_claimed\": \"blue\"\n  },\n  \"LessWrong\": {\n    \"url\": \"https://www.lesswrong.com/users/{}\",\n    \"urlMain\": \"https://www.lesswrong.com/\",\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://www.lesswrong.com/\",\n    \"username_claimed\": \"habryka\"\n  },\n  \"Letterboxd\": {\n    \"errorMsg\": \"Sorry, we can\\u2019t find the page you\\u2019ve requested.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://letterboxd.com/{}\",\n    \"urlMain\": \"https://letterboxd.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"LibraryThing\": {\n    \"errorMsg\": \"<p>Error: This user doesn't exist</p>\",\n    \"errorType\": \"message\",\n    \"headers\": {\n      \"Cookie\": \"LTAnonSessionID=3159599315; LTUnifiedCookie=%7B%22areyouhuman%22%3A1%7D; \"\n    },\n    \"url\": \"https://www.librarything.com/profile/{}\",\n    \"urlMain\": \"https://www.librarything.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Lichess\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://lichess.org/@/{}\",\n    \"urlMain\": \"https://lichess.org\",\n    \"username_claimed\": \"john\"\n  },\n \"LinkedIn\": {\n    \"errorType\": \"status_code\",\n    \"headers\": {\n      \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\",\n      \"Accept-Language\": \"en-US,en;q=0.9\",\n      \"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\"\n    },\n    \"regexCheck\": \"^[a-zA-Z0-9]{3,100}$\",\n    \"request_method\": \"GET\",\n    \"url\": \"https://linkedin.com/in/{}\",\n    \"urlMain\": \"https://linkedin.com\",\n    \"username_claimed\": \"paulpfeister\"\n  },\n  \"Linktree\": {\n    \"errorMsg\": \"\\\"statusCode\\\":404\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[\\\\w\\\\.]{2,30}$\",\n    \"url\": \"https://linktr.ee/{}\",\n    \"urlMain\": \"https://linktr.ee/\",\n    \"username_claimed\": \"anne\"\n  },\n  \"LinuxFR.org\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://linuxfr.org/users/{}\",\n    \"urlMain\": \"https://linuxfr.org/\",\n    \"username_claimed\": \"pylapp\"\n  },\n  \"Listed\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://listed.to/@{}\",\n    \"url\": \"https://listed.to/@{}\",\n    \"urlMain\": \"https://listed.to/\",\n    \"username_claimed\": \"listed\"\n  },\n  \"LiveJournal\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z][a-zA-Z0-9_-]*$\",\n    \"url\": \"https://{}.livejournal.com\",\n    \"urlMain\": \"https://www.livejournal.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Lobsters\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"[A-Za-z0-9][A-Za-z0-9_-]{0,24}\",\n    \"url\": \"https://lobste.rs/u/{}\",\n    \"urlMain\": \"https://lobste.rs/\",\n    \"username_claimed\": \"jcs\"\n  },\n  \"LottieFiles\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://lottiefiles.com/{}\",\n    \"urlMain\": \"https://lottiefiles.com/\",\n    \"username_claimed\": \"lottiefiles\"\n  },\n  \"LushStories\": {\n    \"errorType\": \"status_code\",\n    \"isNSFW\": true,\n    \"url\": \"https://www.lushstories.com/profile/{}\",\n    \"urlMain\": \"https://www.lushstories.com/\",\n    \"username_claimed\": \"chris_brown\"\n  },\n  \"MMORPG Forum\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://forums.mmorpg.com/profile/{}\",\n    \"urlMain\": \"https://forums.mmorpg.com/\",\n    \"username_claimed\": \"goku\"\n  },\n  \"Mamot\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z0-9_]{1,30}$\",\n    \"url\": \"https://mamot.fr/@{}\",\n    \"urlMain\": \"https://mamot.fr/\",\n    \"username_claimed\": \"anciensEnssat\"\n  },\n  \"Medium\": {\n    \"errorMsg\": \"<body\",\n    \"errorType\": \"message\",\n    \"url\": \"https://medium.com/@{}\",\n    \"urlMain\": \"https://medium.com/\",\n    \"urlProbe\": \"https://medium.com/feed/@{}\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Memrise\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.memrise.com/user/{}/\",\n    \"urlMain\": \"https://www.memrise.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Minecraft\": {\n    \"errorMsg\": \"Couldn't find any profile with name\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^.{1,25}$\",\n    \"url\": \"https://api.mojang.com/users/profiles/minecraft/{}\",\n    \"urlMain\": \"https://minecraft.net/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"MixCloud\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.mixcloud.com/{}/\",\n    \"urlMain\": \"https://www.mixcloud.com/\",\n    \"urlProbe\": \"https://api.mixcloud.com/{}/\",\n    \"username_claimed\": \"jenny\"\n  },\n  \"Monkeytype\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://monkeytype.com/profile/{}\",\n    \"urlMain\": \"https://monkeytype.com/\",\n    \"urlProbe\": \"https://api.monkeytype.com/users/{}/profile\",\n    \"username_claimed\": \"Lost_Arrow\"\n  },\n  \"Motherless\": {\n    \"errorMsg\": \"no longer a member\",\n    \"errorType\": \"message\",\n    \"isNSFW\": true,\n    \"url\": \"https://motherless.com/m/{}\",\n    \"urlMain\": \"https://motherless.com/\",\n    \"username_claimed\": \"hacker\"\n  },\n  \"Motorradfrage\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.motorradfrage.net/nutzer/{}\",\n    \"urlMain\": \"https://www.motorradfrage.net/\",\n    \"username_claimed\": \"gutefrage\"\n  },\n  \"MuseScore\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://musescore.com/{}\",\n    \"urlMain\": \"https://musescore.com/\",\n    \"username_claimed\": \"arrangeme\",\n    \"request_method\": \"GET\"\n  },\n  \"MyAnimeList\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://myanimelist.net/profile/{}\",\n    \"urlMain\": \"https://myanimelist.net/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"MyMiniFactory\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.myminifactory.com/users/{}\",\n    \"urlMain\": \"https://www.myminifactory.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Mydramalist\": {\n    \"errorMsg\": \"The requested page was not found\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.mydramalist.com/profile/{}\",\n    \"urlMain\": \"https://mydramalist.com\",\n    \"username_claimed\": \"elhadidy12398\"\n  },\n  \"Myspace\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://myspace.com/{}\",\n    \"urlMain\": \"https://myspace.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"NICommunityForum\": {\n    \"errorMsg\": \"The page you were looking for could not be found.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://community.native-instruments.com/profile/{}\",\n    \"urlMain\": \"https://www.native-instruments.com/forum/\",\n    \"username_claimed\": \"jambert\"\n  },\n  \"namuwiki\": {\n    \"__comment__\": \"This is a Korean site and it's expected to return false negatives in certain other regions.\",\n    \"errorType\": \"status_code\",\n    \"url\": \"https://namu.wiki/w/%EC%82%AC%EC%9A%A9%EC%9E%90:{}\",\n    \"urlMain\": \"https://namu.wiki/\",\n    \"username_claimed\": \"namu\"\n  },\n  \"NationStates Nation\": {\n    \"errorMsg\": \"Was this your nation? It may have ceased to exist due to inactivity, but can rise again!\",\n    \"errorType\": \"message\",\n    \"url\": \"https://nationstates.net/nation={}\",\n    \"urlMain\": \"https://nationstates.net\",\n    \"username_claimed\": \"the_holy_principality_of_saint_mark\"\n  },\n  \"NationStates Region\": {\n    \"errorMsg\": \"does not exist.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://nationstates.net/region={}\",\n    \"urlMain\": \"https://nationstates.net\",\n    \"username_claimed\": \"the_west_pacific\"\n  },\n  \"Naver\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://blog.naver.com/{}\",\n    \"urlMain\": \"https://naver.com\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Needrom\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.needrom.com/author/{}/\",\n    \"urlMain\": \"https://www.needrom.com/\",\n    \"username_claimed\": \"needrom\"\n  },\n  \"Newgrounds\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z][a-zA-Z0-9_-]*$\",\n    \"url\": \"https://{}.newgrounds.com\",\n    \"urlMain\": \"https://newgrounds.com\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Nextcloud Forum\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^(?![.-])[a-zA-Z0-9_.-]{3,20}$\",\n    \"url\": \"https://help.nextcloud.com/u/{}/summary\",\n    \"urlMain\": \"https://nextcloud.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Nightbot\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://nightbot.tv/t/{}/commands\",\n    \"urlMain\": \"https://nightbot.tv/\",\n    \"urlProbe\": \"https://api.nightbot.tv/1/channels/t/{}\",\n    \"username_claimed\": \"green\"\n  },\n  \"Ninja Kiwi\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://ninjakiwi.com/profile/{}\",\n    \"url\": \"https://ninjakiwi.com/profile/{}\",\n    \"urlMain\": \"https://ninjakiwi.com/\",\n    \"username_claimed\": \"Kyruko\"\n  },\n  \"NintendoLife\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.nintendolife.com/users/{}\",\n    \"urlMain\": \"https://www.nintendolife.com/\",\n    \"username_claimed\": \"goku\"\n  },\n  \"NitroType\": {\n    \"errorMsg\": \"<title>Nitro Type | Competitive Typing Game | Race Your Friends</title>\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.nitrotype.com/racer/{}\",\n    \"urlMain\": \"https://www.nitrotype.com/\",\n    \"username_claimed\": \"jianclash\"\n  },\n  \"NotABug.org\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://notabug.org/{}\",\n    \"urlMain\": \"https://notabug.org/\",\n    \"urlProbe\": \"https://notabug.org/{}/followers\",\n    \"username_claimed\": \"red\"\n  },\n  \"Nothing Community\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://nothing.community/u/{}\",\n    \"urlMain\": \"https://nothing.community/\",\n    \"username_claimed\": \"Carl\"\n  },\n  \"Nyaa.si\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://nyaa.si/user/{}\",\n    \"urlMain\": \"https://nyaa.si/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"ObservableHQ\": {\n    \"errorType\": \"message\",\n    \"errorMsg\": \"Page not found\",\n    \"url\": \"https://observablehq.com/@{}\",\n    \"urlMain\": \"https://observablehq.com/\",\n    \"username_claimed\": \"mbostock\"\n  },\n  \"Open Collective\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://opencollective.com/{}\",\n    \"urlMain\": \"https://opencollective.com/\",\n    \"username_claimed\": \"sindresorhus\"\n  },\n  \"OpenGameArt\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://opengameart.org/users/{}\",\n    \"urlMain\": \"https://opengameart.org\",\n    \"username_claimed\": \"ski\"\n  },\n  \"OpenStreetMap\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[^.]*?$\",\n    \"url\": \"https://www.openstreetmap.org/user/{}\",\n    \"urlMain\": \"https://www.openstreetmap.org/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Odysee\": {\n    \"errorMsg\": \"<link rel=\\\"canonical\\\" content=\\\"odysee.com\\\"/>\",\n    \"errorType\": \"message\",\n    \"url\": \"https://odysee.com/@{}\",\n    \"urlMain\": \"https://odysee.com/\",\n    \"username_claimed\": \"Odysee\"\n  },\n  \"Opensource\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://opensource.com/users/{}\",\n    \"urlMain\": \"https://opensource.com/\",\n    \"username_claimed\": \"red\"\n  },\n  \"OurDJTalk\": {\n    \"errorMsg\": \"The specified member cannot be found\",\n    \"errorType\": \"message\",\n    \"url\": \"https://ourdjtalk.com/members?username={}\",\n    \"urlMain\": \"https://ourdjtalk.com/\",\n    \"username_claimed\": \"steve\"\n  },\n  \"Outgress\": {\n    \"errorMsg\": \"Outgress - Error\",\n    \"errorType\": \"message\",\n    \"url\": \"https://outgress.com/agents/{}\",\n    \"urlMain\": \"https://outgress.com/\",\n    \"username_claimed\": \"pylapp\"\n  },\n  \"PCGamer\": {\n    \"errorMsg\": \"The specified member cannot be found. Please enter a member's entire name.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://forums.pcgamer.com/members/?username={}\",\n    \"urlMain\": \"https://pcgamer.com\",\n    \"username_claimed\": \"admin\"\n  },\n  \"PSNProfiles.com\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://psnprofiles.com/?psnId={}\",\n    \"url\": \"https://psnprofiles.com/{}\",\n    \"urlMain\": \"https://psnprofiles.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Packagist\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://packagist.org/search/?q={}&reason=vendor_not_found\",\n    \"url\": \"https://packagist.org/packages/{}/\",\n    \"urlMain\": \"https://packagist.org/\",\n    \"username_claimed\": \"psr\"\n  },\n  \"Pastebin\": {\n    \"errorMsg\": \"Not Found (#404)\",\n    \"errorType\": \"message\",\n    \"url\": \"https://pastebin.com/u/{}\",\n    \"urlMain\": \"https://pastebin.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Patched\": {\n    \"errorMsg\": \"The member you specified is either invalid or doesn't exist.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://patched.sh/User/{}\",\n    \"urlMain\": \"https://patched.sh/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Patreon\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.patreon.com/{}\",\n    \"urlMain\": \"https://www.patreon.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"PentesterLab\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[\\\\w]{4,30}$\",\n    \"url\": \"https://pentesterlab.com/profile/{}\",\n    \"urlMain\": \"https://pentesterlab.com/\",\n    \"username_claimed\": \"0day\"\n  },\n  \"HotUKdeals\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.hotukdeals.com/profile/{}\",\n    \"urlMain\": \"https://www.hotukdeals.com/\",\n    \"username_claimed\": \"Blue\",\n    \"request_method\": \"GET\"\n  },\n  \"Mydealz\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.mydealz.de/profile/{}\",\n    \"urlMain\": \"https://www.mydealz.de/\",\n    \"username_claimed\": \"blue\",\n    \"request_method\": \"GET\"\n  },\n  \"Chollometro\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.chollometro.com/profile/{}\",\n    \"urlMain\": \"https://www.chollometro.com/\",\n    \"username_claimed\": \"blue\",\n    \"request_method\": \"GET\"\n  },\n  \"PepperNL\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://nl.pepper.com/profile/{}\",\n    \"urlMain\": \"https://nl.pepper.com/\",\n    \"username_claimed\": \"Dynaw\",\n    \"request_method\": \"GET\"\n  },\n  \"PepperPL\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.pepper.pl/profile/{}\",\n    \"urlMain\": \"https://www.pepper.pl/\",\n    \"username_claimed\": \"FireChicken\",\n    \"request_method\": \"GET\"\n  },\n  \"Preisjaeger\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.preisjaeger.at/profile/{}\",\n    \"urlMain\": \"https://www.preisjaeger.at/\",\n    \"username_claimed\": \"Stefan\",\n    \"request_method\": \"GET\"\n  },\n  \"Pepperdeals\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.pepperdeals.se/profile/{}\",\n    \"urlMain\": \"https://www.pepperdeals.se/\",\n    \"username_claimed\": \"Mark\",\n    \"request_method\": \"GET\"\n  },\n  \"PepperealsUS\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.pepperdeals.com/profile/{}\",\n    \"urlMain\": \"https://www.pepperdeals.com/\",\n    \"username_claimed\": \"Stepan\",\n    \"request_method\": \"GET\"\n  },\n  \"Promodescuentos\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.promodescuentos.com/profile/{}\",\n    \"urlMain\": \"https://www.promodescuentos.com/\",\n    \"username_claimed\": \"blue\",\n    \"request_method\": \"GET\"\n  },\n  \"Periscope\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.periscope.tv/{}/\",\n    \"urlMain\": \"https://www.periscope.tv/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Pinkbike\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[^.]*?$\",\n    \"url\": \"https://www.pinkbike.com/u/{}/\",\n    \"urlMain\": \"https://www.pinkbike.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"pixelfed.social\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://pixelfed.social/{}/\",\n    \"urlMain\": \"https://pixelfed.social\",\n    \"username_claimed\": \"pylapp\"\n  },\n  \"PlayStore\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://play.google.com/store/apps/developer?id={}\",\n    \"urlMain\": \"https://play.google.com/store\",\n    \"username_claimed\": \"Facebook\"\n  },\n  \"Playstrategy\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://playstrategy.org/@/{}\",\n    \"urlMain\": \"https://playstrategy.org\",\n    \"username_claimed\": \"oruro\"\n  },\n  \"Plurk\": {\n    \"errorMsg\": \"User Not Found!\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.plurk.com/{}\",\n    \"urlMain\": \"https://www.plurk.com/\",\n    \"username_claimed\": \"plurkoffice\"\n  },\n  \"PocketStars\": {\n    \"errorMsg\": \"Join Your Favorite Adult Stars\",\n    \"errorType\": \"message\",\n    \"isNSFW\": true,\n    \"url\": \"https://pocketstars.com/{}\",\n    \"urlMain\": \"https://pocketstars.com/\",\n    \"username_claimed\": \"hacker\"\n  },\n  \"Pokemon Showdown\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://pokemonshowdown.com/users/{}\",\n    \"urlMain\": \"https://pokemonshowdown.com\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Polarsteps\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://polarsteps.com/{}\",\n    \"urlMain\": \"https://polarsteps.com/\",\n    \"urlProbe\": \"https://api.polarsteps.com/users/byusername/{}\",\n    \"username_claimed\": \"james\"\n  },\n  \"Polygon\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.polygon.com/users/{}\",\n    \"urlMain\": \"https://www.polygon.com/\",\n    \"username_claimed\": \"swiftstickler\"\n  },\n  \"Polymart\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://polymart.org/user/-1\",\n    \"url\": \"https://polymart.org/user/{}\",\n    \"urlMain\": \"https://polymart.org/\",\n    \"username_claimed\": \"craciu25yt\"\n  },\n  \"Pornhub\": {\n    \"errorType\": \"status_code\",\n    \"isNSFW\": true,\n    \"url\": \"https://pornhub.com/users/{}\",\n    \"urlMain\": \"https://pornhub.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"ProductHunt\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.producthunt.com/@{}\",\n    \"urlMain\": \"https://www.producthunt.com/\",\n    \"username_claimed\": \"jenny\"\n  },\n  \"programming.dev\": {\n    \"errorMsg\": \"Error!\",\n    \"errorType\": \"message\",\n    \"url\": \"https://programming.dev/u/{}\",\n    \"urlMain\": \"https://programming.dev\",\n    \"username_claimed\": \"pylapp\"\n  },\n  \"Pychess\": {\n    \"errorType\": \"message\",\n    \"errorMsg\": \"404\",\n    \"url\": \"https://www.pychess.org/@/{}\",\n    \"urlMain\": \"https://www.pychess.org\",\n    \"username_claimed\": \"gbtami\"\n  },\n  \"PromoDJ\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"http://promodj.com/{}\",\n    \"urlMain\": \"http://promodj.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Pronouns.page\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://pronouns.page/@{}\",\n    \"urlMain\": \"https://pronouns.page/\",\n    \"username_claimed\": \"andrea\"\n  },\n  \"PyPi\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://pypi.org/user/{}\",\n    \"urlProbe\": \"https://pypi.org/_includes/administer-user-include/{}\",\n    \"urlMain\": \"https://pypi.org\",\n    \"username_claimed\": \"Blue\"\n  },\n  \"Python.org Discussions\": {\n    \"errorMsg\": \"Oops! That page doesn’t exist or is private.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://discuss.python.org/u/{}/summary\",\n    \"urlMain\": \"https://discuss.python.org\",\n    \"username_claimed\": \"pablogsal\"\n  },\n  \"Rajce.net\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[\\\\w@-]+?$\",\n    \"url\": \"https://{}.rajce.idnes.cz/\",\n    \"urlMain\": \"https://www.rajce.idnes.cz/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Rarible\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://rarible.com/marketplace/api/v4/urls/{}\",\n    \"urlMain\": \"https://rarible.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Rate Your Music\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://rateyourmusic.com/~{}\",\n    \"urlMain\": \"https://rateyourmusic.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Rclone Forum\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://forum.rclone.org/u/{}\",\n    \"urlMain\": \"https://forum.rclone.org/\",\n    \"username_claimed\": \"ncw\"\n  },\n  \"RedTube\": {\n    \"errorType\": \"status_code\",\n    \"isNSFW\": true,\n    \"url\": \"https://www.redtube.com/users/{}\",\n    \"urlMain\": \"https://www.redtube.com/\",\n    \"username_claimed\": \"hacker\"\n  },\n  \"Redbubble\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.redbubble.com/people/{}\",\n    \"urlMain\": \"https://www.redbubble.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Reddit\": {\n    \"errorMsg\": \"Sorry, nobody on Reddit goes by that name.\",\n    \"errorType\": \"message\",\n    \"headers\": {\n      \"accept-language\": \"en-US,en;q=0.9\"\n    },\n    \"url\": \"https://www.reddit.com/user/{}\",\n    \"urlMain\": \"https://www.reddit.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Realmeye\": {\n    \"errorMsg\": \"Sorry, but we either:\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.realmeye.com/player/{}\",\n    \"urlMain\": \"https://www.realmeye.com/\",\n    \"username_claimed\": \"rotmg\"\n  },\n  \"Reisefrage\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.reisefrage.net/nutzer/{}\",\n    \"urlMain\": \"https://www.reisefrage.net/\",\n    \"username_claimed\": \"reisefrage\"\n  },\n  \"Replit.com\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://replit.com/@{}\",\n    \"urlMain\": \"https://replit.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"ResearchGate\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://www.researchgate.net/directory/profiles\",\n    \"regexCheck\": \"\\\\w+_\\\\w+\",\n    \"url\": \"https://www.researchgate.net/profile/{}\",\n    \"urlMain\": \"https://www.researchgate.net/\",\n    \"username_claimed\": \"John_Smith\"\n  },\n  \"ReverbNation\": {\n    \"errorMsg\": \"Sorry, we couldn't find that page\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.reverbnation.com/{}\",\n    \"urlMain\": \"https://www.reverbnation.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Roblox\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.roblox.com/user.aspx?username={}\",\n    \"urlMain\": \"https://www.roblox.com/\",\n    \"username_claimed\": \"bluewolfekiller\"\n  },\n  \"RocketTube\": {\n    \"errorMsg\": \"OOPS! Houston, we have a problem\",\n    \"errorType\": \"message\",\n    \"isNSFW\": true,\n    \"url\": \"https://www.rockettube.com/{}\",\n    \"urlMain\": \"https://www.rockettube.com/\",\n    \"username_claimed\": \"Tatteddick5600\"\n  },\n  \"RoyalCams\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://royalcams.com/profile/{}\",\n    \"urlMain\": \"https://royalcams.com\",\n    \"username_claimed\": \"asuna-black\"\n  },\n  \"Ruby Forums\": {\n    \"errorMsg\": \"Oops! That page doesn’t exist or is private.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://ruby-forum.com/u/{}/summary\",\n    \"urlMain\": \"https://ruby-forums.com\",\n    \"username_claimed\": \"rishard\"\n  },\n  \"RubyGems\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z][a-zA-Z0-9_-]{1,40}\",\n    \"url\": \"https://rubygems.org/profiles/{}\",\n    \"urlMain\": \"https://rubygems.org/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Rumble\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://rumble.com/user/{}\",\n    \"urlMain\": \"https://rumble.com/\",\n    \"username_claimed\": \"John\"\n  },\n  \"RuneScape\": {\n    \"errorMsg\": \"{\\\"error\\\":\\\"NO_PROFILE\\\",\\\"loggedIn\\\":\\\"false\\\"}\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^(?! )[\\\\w -]{1,12}(?<! )$\",\n    \"url\": \"https://apps.runescape.com/runemetrics/app/overview/player/{}\",\n    \"urlMain\": \"https://www.runescape.com/\",\n    \"urlProbe\": \"https://apps.runescape.com/runemetrics/profile/profile?user={}\",\n    \"username_claimed\": \"L33\"\n  },\n  \"SWAPD\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://swapd.co/u/{}\",\n    \"urlMain\": \"https://swapd.co/\",\n    \"username_claimed\": \"swapd\"\n  },\n  \"Sbazar.cz\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.sbazar.cz/{}\",\n    \"urlMain\": \"https://www.sbazar.cz/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Scratch\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://scratch.mit.edu/users/{}\",\n    \"urlMain\": \"https://scratch.mit.edu/\",\n    \"username_claimed\": \"griffpatch\"\n  },\n  \"Scribd\": {\n    \"errorMsg\": \"Page not found\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.scribd.com/{}\",\n    \"urlMain\": \"https://www.scribd.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"SEOForum\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://seoforum.com/@{}\",\n    \"urlMain\": \"https://www.seoforum.com/\",\n    \"username_claimed\": \"ko\"\n  },\n  \"Shelf\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.shelf.im/{}\",\n    \"urlMain\": \"https://www.shelf.im/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"ShitpostBot5000\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.shitpostbot.com/user/{}\",\n    \"urlMain\": \"https://www.shitpostbot.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Signal\": {\n    \"errorMsg\": \"Oops! That page doesn\\u2019t exist or is private.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://community.signalusers.org/u/{}\",\n    \"urlMain\": \"https://community.signalusers.org\",\n    \"username_claimed\": \"jlund\"\n  },\n  \"Sketchfab\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://sketchfab.com/{}\",\n    \"urlMain\": \"https://sketchfab.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Slack\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z][a-zA-Z0-9_-]*$\",\n    \"url\": \"https://{}.slack.com\",\n    \"urlMain\": \"https://slack.com\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Slant\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^.{2,32}$\",\n    \"url\": \"https://www.slant.co/users/{}\",\n    \"urlMain\": \"https://www.slant.co/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Slashdot\": {\n    \"errorMsg\": \"user you requested does not exist\",\n    \"errorType\": \"message\",\n    \"url\": \"https://slashdot.org/~{}\",\n    \"urlMain\": \"https://slashdot.org\",\n    \"username_claimed\": \"blue\"\n  },\n  \"SlideShare\": {\n    \"errorType\": \"message\",\n    \"errorMsg\": \"<title>Page no longer exists</title>\",\n    \"url\": \"https://slideshare.net/{}\",\n    \"urlMain\": \"https://slideshare.net/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Slides\": {\n    \"errorCode\": 204,\n    \"errorType\": \"status_code\",\n    \"url\": \"https://slides.com/{}\",\n    \"urlMain\": \"https://slides.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"SmugMug\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z]{1,35}$\",\n    \"url\": \"https://{}.smugmug.com\",\n    \"urlMain\": \"https://smugmug.com\",\n    \"username_claimed\": \"winchester\"\n  },\n  \"Smule\": {\n    \"errorMsg\": \"Smule | Page Not Found (404)\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.smule.com/{}\",\n    \"urlMain\": \"https://www.smule.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Snapchat\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-z][a-z-_.]{3,15}\",\n    \"request_method\": \"GET\",\n    \"url\": \"https://www.snapchat.com/add/{}\",\n    \"urlMain\": \"https://www.snapchat.com\",\n    \"username_claimed\": \"teamsnapchat\"\n  },\n  \"SOOP\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.sooplive.co.kr/station/{}\",\n    \"urlMain\": \"https://www.sooplive.co.kr/\",\n    \"urlProbe\": \"https://api-channel.sooplive.co.kr/v1.1/channel/{}/station\",\n    \"username_claimed\": \"udkn\"\n  },\n  \"SoundCloud\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://soundcloud.com/{}\",\n    \"urlMain\": \"https://soundcloud.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"SourceForge\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://sourceforge.net/u/{}\",\n    \"urlMain\": \"https://sourceforge.net/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"SoylentNews\": {\n    \"errorMsg\": \"The user you requested does not exist, no matter how much you wish this might be the case.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://soylentnews.org/~{}\",\n    \"urlMain\": \"https://soylentnews.org\",\n    \"username_claimed\": \"adam\"\n  },\n  \"SpeakerDeck\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://speakerdeck.com/{}\",\n    \"urlMain\": \"https://speakerdeck.com/\",\n    \"username_claimed\": \"pylapp\"\n  },\n  \"Speedrun.com\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://speedrun.com/users/{}\",\n    \"urlMain\": \"https://speedrun.com/\",\n    \"username_claimed\": \"example\"\n  },\n  \"Spells8\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://forum.spells8.com/u/{}\",\n    \"urlMain\": \"https://spells8.com\",\n    \"username_claimed\": \"susurrus\"\n  },\n  \"Splice\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://splice.com/{}\",\n    \"urlMain\": \"https://splice.com/\",\n    \"username_claimed\": \"splice\"\n  },\n  \"Splits.io\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[^.]*?$\",\n    \"url\": \"https://splits.io/users/{}\",\n    \"urlMain\": \"https://splits.io\",\n    \"username_claimed\": \"cambosteve\"\n  },\n  \"Sporcle\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.sporcle.com/user/{}/people\",\n    \"urlMain\": \"https://www.sporcle.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Sportlerfrage\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.sportlerfrage.net/nutzer/{}\",\n    \"urlMain\": \"https://www.sportlerfrage.net/\",\n    \"username_claimed\": \"sportlerfrage\"\n  },\n  \"SportsRU\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.sports.ru/profile/{}/\",\n    \"urlMain\": \"https://www.sports.ru/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Spotify\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://open.spotify.com/user/{}\",\n    \"urlMain\": \"https://open.spotify.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Star Citizen\": {\n    \"errorMsg\": \"404\",\n    \"errorType\": \"message\",\n    \"url\": \"https://robertsspaceindustries.com/citizens/{}\",\n    \"urlMain\": \"https://robertsspaceindustries.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Status Cafe\": {\n    \"errorMsg\": \"Page Not Found\",\n    \"errorType\": \"message\",\n    \"url\": \"https://status.cafe/users/{}\",\n    \"urlMain\": \"https://status.cafe/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Steam Community (Group)\": {\n    \"errorMsg\": \"No group could be retrieved for the given URL\",\n    \"errorType\": \"message\",\n    \"url\": \"https://steamcommunity.com/groups/{}\",\n    \"urlMain\": \"https://steamcommunity.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Steam Community (User)\": {\n    \"errorMsg\": \"The specified profile could not be found\",\n    \"errorType\": \"message\",\n    \"url\": \"https://steamcommunity.com/id/{}/\",\n    \"urlMain\": \"https://steamcommunity.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Strava\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[^.]*?$\",\n    \"url\": \"https://www.strava.com/athletes/{}\",\n    \"urlMain\": \"https://www.strava.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"SublimeForum\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://forum.sublimetext.com/u/{}\",\n    \"urlMain\": \"https://forum.sublimetext.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"TETR.IO\": {\n    \"errorMsg\": \"No such user!\",\n    \"errorType\": \"message\",\n    \"url\": \"https://ch.tetr.io/u/{}\",\n    \"urlMain\": \"https://tetr.io\",\n    \"urlProbe\": \"https://ch.tetr.io/api/users/{}\",\n    \"username_claimed\": \"osk\"\n  },\n  \"TheMovieDB\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.themoviedb.org/u/{}\",\n    \"urlMain\": \"https://www.themoviedb.org/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"TikTok\": {\n    \"url\": \"https://www.tiktok.com/@{}\",\n    \"urlMain\": \"https://www.tiktok.com\",\n    \"errorType\": \"message\",\n    \"errorMsg\": [\n      \"\\\"statusCode\\\":10221\",\n      \"Govt. of India decided to block 59 apps\"\n    ],\n    \"username_claimed\": \"charlidamelio\"\n  },\n  \"Tiendanube\": {\n    \"url\": \"https://{}.mitiendanube.com/\",\n    \"urlMain\": \"https://www.tiendanube.com/\",\n    \"errorType\": \"status_code\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Topcoder\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://profiles.topcoder.com/{}/\",\n    \"urlMain\": \"https://topcoder.com/\",\n    \"username_claimed\": \"USER\",\n    \"urlProbe\": \"https://api.topcoder.com/v5/members/{}\",\n    \"regexCheck\": \"^[a-zA-Z0-9_.]+$\"\n  },\n  \"Topmate\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://topmate.io/{}\",\n    \"urlMain\": \"https://topmate.io/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"TRAKTRAIN\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://traktrain.com/{}\",\n    \"urlMain\": \"https://traktrain.com/\",\n    \"username_claimed\": \"traktrain\"\n  },\n  \"Telegram\": {\n    \"errorMsg\": [\n      \"<title>Telegram Messenger</title>\",\n      \"If you have <strong>Telegram</strong>, you can contact <a class=\\\"tgme_username_link\\\" href=\\\"tg://resolve?domain=\"\n    ],\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[a-zA-Z0-9_]{3,32}[^_]$\",\n    \"url\": \"https://t.me/{}\",\n    \"urlMain\": \"https://t.me/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Tellonym.me\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://tellonym.me/{}\",\n    \"urlMain\": \"https://tellonym.me/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Tenor\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[A-Za-z0-9_]{2,32}$\",\n    \"url\": \"https://tenor.com/users/{}\",\n    \"urlMain\": \"https://tenor.com/\",\n    \"username_claimed\": \"red\"\n  },\n  \"Terraria Forums\": {\n    \"errorMsg\": \"The following members could not be found\",\n    \"errorType\": \"message\",\n    \"url\": \"https://forums.terraria.org/index.php?search/42798315/&c[users]={}&o=relevance\",\n    \"urlMain\": \"https://forums.terraria.org/index.php\",\n    \"username_claimed\": \"blue\"\n  },\n  \"ThemeForest\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://themeforest.net/user/{}\",\n    \"urlMain\": \"https://themeforest.net/\",\n    \"username_claimed\": \"user\"\n  },\n  \"tistory\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://{}.tistory.com/\",\n    \"urlMain\": \"https://www.tistory.com/\",\n    \"username_claimed\": \"notice\"\n  },\n  \"TnAFlix\": {\n    \"errorType\": \"status_code\",\n    \"isNSFW\": true,\n    \"url\": \"https://www.tnaflix.com/profile/{}\",\n    \"urlMain\": \"https://www.tnaflix.com/\",\n    \"username_claimed\": \"hacker\"\n  },\n  \"TradingView\": {\n    \"errorType\": \"status_code\",\n    \"request_method\": \"GET\",\n    \"url\": \"https://www.tradingview.com/u/{}/\",\n    \"urlMain\": \"https://www.tradingview.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Trakt\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[^.]*$\",\n    \"url\": \"https://www.trakt.tv/users/{}\",\n    \"urlMain\": \"https://www.trakt.tv/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"TrashboxRU\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[A-Za-z0-9_-]{3,16}$\",\n    \"url\": \"https://trashbox.ru/users/{}\",\n    \"urlMain\": \"https://trashbox.ru/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Trawelling\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://traewelling.de/@{}\",\n    \"urlMain\": \"https://traewelling.de/\",\n    \"username_claimed\": \"lassestolley\"\n  },\n  \"Trello\": {\n    \"errorMsg\": \"model not found\",\n    \"errorType\": \"message\",\n    \"url\": \"https://trello.com/{}\",\n    \"urlMain\": \"https://trello.com/\",\n    \"urlProbe\": \"https://trello.com/1/Members/{}\",\n    \"username_claimed\": \"blue\"\n  },\n  \"TryHackMe\": {\n    \"errorMsg\": \"{\\\"success\\\":false}\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[a-zA-Z0-9.]{1,16}$\",\n    \"url\": \"https://tryhackme.com/p/{}\",\n    \"urlMain\": \"https://tryhackme.com/\",\n    \"urlProbe\": \"https://tryhackme.com/api/user/exist/{}\",\n    \"username_claimed\": \"ashu\"\n  },\n  \"Tuna\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-z0-9]{4,40}$\",\n    \"url\": \"https://tuna.voicemod.net/user/{}\",\n    \"urlMain\": \"https://tuna.voicemod.net/\",\n    \"username_claimed\": \"bob\"\n  },\n  \"Tweakers\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://tweakers.net/gallery/{}\",\n    \"urlMain\": \"https://tweakers.net\",\n    \"username_claimed\": \"femme\"\n  },\n  \"Twitch\": {\n    \"errorMsg\": \"content='Twitch is the world&#39;s leading video platform and community for gamers.'\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.twitch.tv/{}\",\n    \"urlMain\": \"https://www.twitch.tv\",\n    \"username_claimed\": \"xqc\"\n  },\n\n  \"Trovo\": {\n    \"errorMsg\": \"Uh Ohhh...\",\n    \"errorType\": \"message\",\n    \"url\": \"https://trovo.live/s/{}/\",\n    \"urlMain\": \"https://trovo.live\",\n    \"username_claimed\": \"Aimilios\"\n  },\n  \"Twitter\": {\n    \"errorMsg\": [\n      \"<div class=\\\"error-panel\\\"><span>User \",\n      \"<title>429 Too Many Requests</title>\"\n    ],\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[a-zA-Z0-9_]{1,15}$\",\n    \"url\": \"https://x.com/{}\",\n    \"urlMain\": \"https://x.com/\",\n    \"urlProbe\": \"https://nitter.privacydev.net/{}\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Typeracer\": {\n    \"errorMsg\": \"Profile Not Found\",\n    \"errorType\": \"message\",\n    \"url\": \"https://data.typeracer.com/pit/profile?user={}\",\n    \"urlMain\": \"https://typeracer.com\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Ultimate-Guitar\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://ultimate-guitar.com/u/{}\",\n    \"urlMain\": \"https://ultimate-guitar.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Unsplash\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-z0-9_]{1,60}$\",\n    \"url\": \"https://unsplash.com/@{}\",\n    \"urlMain\": \"https://unsplash.com/\",\n    \"username_claimed\": \"jenny\"\n  },\n  \"Untappd\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://untappd.com/user/{}\",\n    \"urlMain\": \"https://untappd.com/\",\n    \"username_claimed\": \"untappd\"\n  },\n  \"Valorant Forums\": {\n    \"errorMsg\": \"The page you requested could not be found.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://valorantforums.com/u/{}\",\n    \"urlMain\": \"https://valorantforums.com\",\n    \"username_claimed\": \"Wolves\"\n  },\n  \"VK\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://www.quora.com/profile/{}\",\n    \"url\": \"https://vk.com/{}\",\n    \"urlMain\": \"https://vk.com/\",\n    \"username_claimed\": \"brown\"\n  },\n  \"VSCO\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://vsco.co/{}\",\n    \"urlMain\": \"https://vsco.co/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Velog\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://velog.io/@{}/posts\",\n    \"urlMain\": \"https://velog.io/\",\n    \"username_claimed\": \"qlgks1\"\n  },\n  \"Velomania\": {\n    \"errorMsg\": \"\\u041f\\u043e\\u043b\\u044c\\u0437\\u043e\\u0432\\u0430\\u0442\\u0435\\u043b\\u044c \\u043d\\u0435 \\u0437\\u0430\\u0440\\u0435\\u0433\\u0438\\u0441\\u0442\\u0440\\u0438\\u0440\\u043e\\u0432\\u0430\\u043d \\u0438 \\u043d\\u0435 \\u0438\\u043c\\u0435\\u0435\\u0442 \\u043f\\u0440\\u043e\\u0444\\u0438\\u043b\\u044f \\u0434\\u043b\\u044f \\u043f\\u0440\\u043e\\u0441\\u043c\\u043e\\u0442\\u0440\\u0430.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://forum.velomania.ru/member.php?username={}\",\n    \"urlMain\": \"https://forum.velomania.ru/\",\n    \"username_claimed\": \"red\"\n  },\n  \"Venmo\": {\n    \"errorMsg\": [\"Venmo | Page Not Found\"],\n    \"errorType\": \"message\",\n    \"headers\": {\n      \"Host\": \"account.venmo.com\"\n    },\n    \"url\": \"https://account.venmo.com/u/{}\",\n    \"urlMain\": \"https://venmo.com/\",\n    \"urlProbe\": \"https://test1.venmo.com/u/{}\",\n    \"username_claimed\": \"jenny\"\n  },\n  \"Vero\": {\n    \"errorMsg\": \"Not Found\",\n    \"errorType\": \"message\",\n    \"request_method\": \"GET\",\n    \"url\": \"https://vero.co/{}\",\n    \"urlMain\": \"https://vero.co/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Vimeo\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://vimeo.com/{}\",\n    \"urlMain\": \"https://vimeo.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"VirusTotal\": {\n    \"errorType\": \"status_code\",\n    \"request_method\": \"GET\",\n    \"url\": \"https://www.virustotal.com/gui/user/{}\",\n    \"urlMain\": \"https://www.virustotal.com/\",\n    \"urlProbe\": \"https://www.virustotal.com/ui/users/{}/avatar\",\n    \"username_claimed\": \"blue\"\n  },\n  \"VLR\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.vlr.gg/user/{}\",\n    \"urlMain\": \"https://www.vlr.gg\",\n    \"username_claimed\": \"optms\"\n  },\n  \"WICG Forum\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^(?![.-])[a-zA-Z0-9_.-]{3,20}$\",\n    \"url\": \"https://discourse.wicg.io/u/{}/summary\",\n    \"urlMain\": \"https://discourse.wicg.io/\",\n    \"username_claimed\": \"stefano\"\n  },\n  \"Wakatime\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://wakatime.com/@{}\",\n    \"urlMain\": \"https://wakatime.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Warrior Forum\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.warriorforum.com/members/{}.html\",\n    \"urlMain\": \"https://www.warriorforum.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Wattpad\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.wattpad.com/user/{}\",\n    \"urlMain\": \"https://www.wattpad.com/\",\n    \"urlProbe\": \"https://www.wattpad.com/api/v3/users/{}/\",\n    \"username_claimed\": \"Dogstho7951\"\n  },\n  \"WebNode\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[\\\\w@-]+?$\",\n    \"url\": \"https://{}.webnode.cz/\",\n    \"urlMain\": \"https://www.webnode.cz/\",\n    \"username_claimed\": \"radkabalcarova\"\n  },\n  \"Weblate\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z0-9@._-]{1,150}$\",\n    \"url\": \"https://hosted.weblate.org/user/{}/\",\n    \"urlMain\": \"https://hosted.weblate.org/\",\n    \"username_claimed\": \"adam\"\n  },\n  \"Weebly\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[a-zA-Z0-9-]{1,63}$\",\n    \"url\": \"https://{}.weebly.com/\",\n    \"urlMain\": \"https://weebly.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Wikidot\": {\n    \"errorMsg\": \"User does not exist.\",\n    \"errorType\": \"message\",\n    \"url\": \"http://www.wikidot.com/user:info/{}\",\n    \"urlMain\": \"http://www.wikidot.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Wikipedia\": {\n    \"errorMsg\": \"centralauth-admin-nonexistent:\",\n    \"errorType\": \"message\",\n    \"url\": \"https://en.wikipedia.org/wiki/Special:CentralAuth/{}?uselang=qqx\",\n    \"urlMain\": \"https://www.wikipedia.org/\",\n    \"username_claimed\": \"Hoadlck\"\n  },\n  \"Windy\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://community.windy.com/user/{}\",\n    \"urlMain\": \"https://windy.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Wix\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[\\\\w@-]+?$\",\n    \"url\": \"https://{}.wix.com\",\n    \"urlMain\": \"https://wix.com/\",\n    \"username_claimed\": \"support\"\n  },\n  \"WolframalphaForum\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://community.wolfram.com/web/{}/home\",\n    \"urlMain\": \"https://community.wolfram.com/\",\n    \"username_claimed\": \"unico\"\n  },\n  \"WordPress\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"wordpress.com/typo/?subdomain=\",\n    \"regexCheck\": \"^[a-zA-Z][a-zA-Z0-9_-]*$\",\n    \"url\": \"https://{}.wordpress.com/\",\n    \"urlMain\": \"https://wordpress.com\",\n    \"username_claimed\": \"blue\"\n  },\n  \"WordPressOrg\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://wordpress.org\",\n    \"url\": \"https://profiles.wordpress.org/{}/\",\n    \"urlMain\": \"https://wordpress.org/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Wordnik\": {\n    \"errorMsg\": \"Page Not Found\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[a-zA-Z0-9_.+-]{1,40}$\",\n    \"url\": \"https://www.wordnik.com/users/{}\",\n    \"urlMain\": \"https://www.wordnik.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Wykop\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.wykop.pl/ludzie/{}\",\n    \"urlMain\": \"https://www.wykop.pl\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Xbox Gamertag\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://xboxgamertag.com/search/{}\",\n    \"urlMain\": \"https://xboxgamertag.com/\",\n    \"username_claimed\": \"red\"\n  },\n  \"Xvideos\": {\n    \"errorType\": \"status_code\",\n    \"isNSFW\": true,\n    \"url\": \"https://xvideos.com/profiles/{}\",\n    \"urlMain\": \"https://xvideos.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"YandexMusic\": {\n    \"__comment__\": \"The first and third errorMsg relate to geo-restrictions and bot detection/captchas.\",\n    \"errorMsg\": [\n      \"\\u041e\\u0448\\u0438\\u0431\\u043a\\u0430 404\",\n      \"<meta name=\\\"description\\\" content=\\\"\\u041e\\u0442\\u043a\\u0440\\u044b\\u0432\\u0430\\u0439\\u0442\\u0435 \\u043d\\u043e\\u0432\\u0443\\u044e \\u043c\\u0443\\u0437\\u044b\\u043a\\u0443 \\u043a\\u0430\\u0436\\u0434\\u044b\\u0439 \\u0434\\u0435\\u043d\\u044c.\",\n      \"<input type=\\\"submit\\\" class=\\\"CheckboxCaptcha-Button\\\"\"\n    ],\n    \"errorType\": \"message\",\n    \"url\": \"https://music.yandex/users/{}/playlists\",\n    \"urlMain\": \"https://music.yandex\",\n    \"username_claimed\": \"ya.playlist\"\n  },\n  \"YouNow\": {\n    \"errorMsg\": \"No users found\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.younow.com/{}/\",\n    \"urlMain\": \"https://www.younow.com/\",\n    \"urlProbe\": \"https://api.younow.com/php/api/broadcast/info/user={}/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"YouPic\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://youpic.com/photographer/{}/\",\n    \"urlMain\": \"https://youpic.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"YouPorn\": {\n    \"errorType\": \"status_code\",\n    \"isNSFW\": true,\n    \"url\": \"https://youporn.com/uservids/{}\",\n    \"urlMain\": \"https://youporn.com\",\n    \"username_claimed\": \"blue\"\n  },\n  \"YouTube\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.youtube.com/@{}\",\n    \"urlMain\": \"https://www.youtube.com/\",\n    \"username_claimed\": \"youtube\"\n  },\n  \"akniga\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://akniga.org/profile/{}\",\n    \"urlMain\": \"https://akniga.org/profile/blue/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"authorSTREAM\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"http://www.authorstream.com/{}/\",\n    \"urlMain\": \"http://www.authorstream.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"babyblogRU\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://www.babyblog.ru/\",\n    \"url\": \"https://www.babyblog.ru/user/{}\",\n    \"urlMain\": \"https://www.babyblog.ru/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"chaos.social\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://chaos.social/@{}\",\n    \"urlMain\": \"https://chaos.social/\",\n    \"username_claimed\": \"rixx\"\n  },\n  \"couchsurfing\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.couchsurfing.com/people/{}\",\n    \"urlMain\": \"https://www.couchsurfing.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"d3RU\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://d3.ru/user/{}/posts\",\n    \"urlMain\": \"https://d3.ru/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"dailykos\": {\n    \"errorMsg\": \"{\\\"result\\\":true,\\\"message\\\":null}\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.dailykos.com/user/{}\",\n    \"urlMain\": \"https://www.dailykos.com\",\n    \"urlProbe\": \"https://www.dailykos.com/signup/check_nickname?nickname={}\",\n    \"username_claimed\": \"blue\"\n  },\n  \"datingRU\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"http://dating.ru/{}\",\n    \"urlMain\": \"http://dating.ru\",\n    \"username_claimed\": \"blue\"\n  },\n  \"devRant\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://devrant.com/\",\n    \"url\": \"https://devrant.com/users/{}\",\n    \"urlMain\": \"https://devrant.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"drive2\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.drive2.ru/users/{}\",\n    \"urlMain\": \"https://www.drive2.ru/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"eGPU\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://egpu.io/forums/profile/{}/\",\n    \"urlMain\": \"https://egpu.io/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"eintracht\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[^.]*?$\",\n    \"url\": \"https://community.eintracht.de/fans/{}\",\n    \"urlMain\": \"https://eintracht.de\",\n    \"username_claimed\": \"blue\"\n  },\n  \"fixya\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.fixya.com/users/{}\",\n    \"urlMain\": \"https://www.fixya.com\",\n    \"username_claimed\": \"adam\"\n  },\n  \"fl\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.fl.ru/users/{}\",\n    \"urlMain\": \"https://www.fl.ru/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"forum_guns\": {\n    \"errorMsg\": \"action=https://forum.guns.ru/forummisc/blog/search\",\n    \"errorType\": \"message\",\n    \"url\": \"https://forum.guns.ru/forummisc/blog/{}\",\n    \"urlMain\": \"https://forum.guns.ru/\",\n    \"username_claimed\": \"red\"\n  },\n  \"freecodecamp\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.freecodecamp.org/{}\",\n    \"urlMain\": \"https://www.freecodecamp.org/\",\n    \"urlProbe\": \"https://api.freecodecamp.org/api/users/get-public-profile?username={}\",\n    \"username_claimed\": \"naveennamani\"\n  },\n  \"furaffinity\": {\n    \"errorMsg\": \"This user cannot be found.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.furaffinity.net/user/{}\",\n    \"urlMain\": \"https://www.furaffinity.net\",\n    \"username_claimed\": \"jesus\"\n  },\n  \"geocaching\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.geocaching.com/p/default.aspx?u={}\",\n    \"urlMain\": \"https://www.geocaching.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"habr\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://habr.com/ru/users/{}\",\n    \"urlMain\": \"https://habr.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"hackster\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.hackster.io/{}\",\n    \"urlMain\": \"https://www.hackster.io\",\n    \"username_claimed\": \"blue\"\n  },\n  \"hunting\": {\n    \"errorMsg\": \"\\u0423\\u043a\\u0430\\u0437\\u0430\\u043d\\u043d\\u044b\\u0439 \\u043f\\u043e\\u043b\\u044c\\u0437\\u043e\\u0432\\u0430\\u0442\\u0435\\u043b\\u044c \\u043d\\u0435 \\u043d\\u0430\\u0439\\u0434\\u0435\\u043d. \\u041f\\u043e\\u0436\\u0430\\u043b\\u0443\\u0439\\u0441\\u0442\\u0430, \\u0432\\u0432\\u0435\\u0434\\u0438\\u0442\\u0435 \\u0434\\u0440\\u0443\\u0433\\u043e\\u0435 \\u0438\\u043c\\u044f.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.hunting.ru/forum/members/?username={}\",\n    \"urlMain\": \"https://www.hunting.ru/forum/\",\n    \"username_claimed\": \"red\"\n  },\n  \"igromania\": {\n    \"errorMsg\": \"\\u041f\\u043e\\u043b\\u044c\\u0437\\u043e\\u0432\\u0430\\u0442\\u0435\\u043b\\u044c \\u043d\\u0435 \\u0437\\u0430\\u0440\\u0435\\u0433\\u0438\\u0441\\u0442\\u0440\\u0438\\u0440\\u043e\\u0432\\u0430\\u043d \\u0438 \\u043d\\u0435 \\u0438\\u043c\\u0435\\u0435\\u0442 \\u043f\\u0440\\u043e\\u0444\\u0438\\u043b\\u044f \\u0434\\u043b\\u044f \\u043f\\u0440\\u043e\\u0441\\u043c\\u043e\\u0442\\u0440\\u0430.\",\n    \"errorType\": \"message\",\n    \"url\": \"http://forum.igromania.ru/member.php?username={}\",\n    \"urlMain\": \"http://forum.igromania.ru/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"interpals\": {\n    \"errorMsg\": \"The requested user does not exist or is inactive\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.interpals.net/{}\",\n    \"urlMain\": \"https://www.interpals.net/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"irecommend\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://irecommend.ru/users/{}\",\n    \"urlMain\": \"https://irecommend.ru/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"jbzd.com.pl\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://jbzd.com.pl/uzytkownik/{}\",\n    \"urlMain\": \"https://jbzd.com.pl/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"jeuxvideo\": {\n    \"errorType\": \"status_code\",\n    \"request_method\": \"GET\",\n    \"url\": \"https://www.jeuxvideo.com/profil/{}\",\n    \"urlMain\": \"https://www.jeuxvideo.com\",\n    \"urlProbe\": \"https://www.jeuxvideo.com/profil/{}?mode=infos\",\n    \"username_claimed\": \"adam\"\n  },\n  \"kofi\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://ko-fi.com/art?=redirect\",\n    \"url\": \"https://ko-fi.com/{}\",\n    \"urlMain\": \"https://ko-fi.com\",\n    \"username_claimed\": \"yeahkenny\"\n  },\n  \"kwork\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://kwork.ru/user/{}\",\n    \"urlMain\": \"https://www.kwork.ru/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"last.fm\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://last.fm/user/{}\",\n    \"urlMain\": \"https://last.fm/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"leasehackr\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://forum.leasehackr.com/u/{}/summary/\",\n    \"urlMain\": \"https://forum.leasehackr.com/\",\n    \"username_claimed\": \"adam\"\n  },\n  \"livelib\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.livelib.ru/reader/{}\",\n    \"urlMain\": \"https://www.livelib.ru/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"mastodon.cloud\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://mastodon.cloud/@{}\",\n    \"urlMain\": \"https://mastodon.cloud/\",\n    \"username_claimed\": \"TheAdmin\"\n  },\n  \"mastodon.social\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://mastodon.social/@{}\",\n    \"urlMain\": \"https://chaos.social/\",\n    \"username_claimed\": \"Gargron\"\n  },\n  \"mastodon.xyz\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://mastodon.xyz/@{}\",\n    \"urlMain\": \"https://mastodon.xyz/\",\n    \"username_claimed\": \"TheKinrar\"\n  },\n  \"mstdn.social\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://mstdn.social/@{}\",\n    \"urlMain\": \"https://mstdn.social/\",\n    \"username_claimed\": \"MagicLike\"\n  },\n  \"mercadolivre\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.mercadolivre.com.br/perfil/{}\",\n    \"urlMain\": \"https://www.mercadolivre.com.br\",\n    \"username_claimed\": \"blue\"\n  },\n  \"minds\": {\n    \"errorMsg\": \"\\\"valid\\\":true\",\n    \"errorType\": \"message\",\n    \"url\": \"https://www.minds.com/{}/\",\n    \"urlMain\": \"https://www.minds.com\",\n    \"urlProbe\": \"https://www.minds.com/api/v3/register/validate?username={}\",\n    \"username_claimed\": \"john\"\n  },\n  \"moikrug\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://moikrug.ru/{}\",\n    \"urlMain\": \"https://moikrug.ru/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"mstdn.io\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://mstdn.io/@{}\",\n    \"urlMain\": \"https://mstdn.io/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"nairaland.com\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.nairaland.com/{}\",\n    \"urlMain\": \"https://www.nairaland.com/\",\n    \"username_claimed\": \"red\"\n  },\n  \"n8n Community\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://community.n8n.io/u/{}/summary\",\n    \"urlMain\": \"https://community.n8n.io/\",\n    \"username_claimed\": \"n8n\"\n  },\n  \"nnRU\": {\n    \"errorType\": \"status_code\",\n    \"regexCheck\": \"^[\\\\w@-]+?$\",\n    \"url\": \"https://{}.www.nn.ru/\",\n    \"urlMain\": \"https://www.nn.ru/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"note\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://note.com/{}\",\n    \"urlMain\": \"https://note.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"npm\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.npmjs.com/~{}\",\n    \"urlMain\": \"https://www.npmjs.com/\",\n    \"username_claimed\": \"kennethsweezy\"\n  },\n  \"omg.lol\": {\n    \"errorMsg\": \"\\\"available\\\": true\",\n    \"errorType\": \"message\",\n    \"url\": \"https://{}.omg.lol\",\n    \"urlMain\": \"https://home.omg.lol\",\n    \"urlProbe\": \"https://api.omg.lol/address/{}/availability\",\n    \"username_claimed\": \"adam\"\n  },\n  \"opennet\": {\n    \"errorMsg\": \"\\u0418\\u043c\\u044f \\u0443\\u0447\\u0430\\u0441\\u0442\\u043d\\u0438\\u043a\\u0430 \\u043d\\u0435 \\u043d\\u0430\\u0439\\u0434\\u0435\\u043d\\u043e\",\n    \"errorType\": \"message\",\n    \"regexCheck\": \"^[^-]*$\",\n    \"url\": \"https://www.opennet.ru/~{}\",\n    \"urlMain\": \"https://www.opennet.ru/\",\n    \"username_claimed\": \"anonismus\"\n  },\n  \"osu!\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://osu.ppy.sh/users/{}\",\n    \"urlMain\": \"https://osu.ppy.sh/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"phpRU\": {\n    \"errorMsg\": \"\\u0423\\u043a\\u0430\\u0437\\u0430\\u043d\\u043d\\u044b\\u0439 \\u043f\\u043e\\u043b\\u044c\\u0437\\u043e\\u0432\\u0430\\u0442\\u0435\\u043b\\u044c \\u043d\\u0435 \\u043d\\u0430\\u0439\\u0434\\u0435\\u043d. \\u041f\\u043e\\u0436\\u0430\\u043b\\u0443\\u0439\\u0441\\u0442\\u0430, \\u0432\\u0432\\u0435\\u0434\\u0438\\u0442\\u0435 \\u0434\\u0440\\u0443\\u0433\\u043e\\u0435 \\u0438\\u043c\\u044f.\",\n    \"errorType\": \"message\",\n    \"url\": \"https://php.ru/forum/members/?username={}\",\n    \"urlMain\": \"https://php.ru/forum/\",\n    \"username_claimed\": \"apple\"\n  },\n  \"pikabu\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://pikabu.ru/@{}\",\n    \"urlMain\": \"https://pikabu.ru/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"Pinterest\": {\n    \"errorType\": \"status_code\",\n    \"errorUrl\": \"https://www.pinterest.com/\",\n    \"url\": \"https://www.pinterest.com/{}/\",\n    \"urlProbe\": \"https://www.pinterest.com/oembed.json?url=https://www.pinterest.com/{}/\",\n    \"urlMain\": \"https://www.pinterest.com/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"pr0gramm\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://pr0gramm.com/user/{}\",\n    \"urlMain\": \"https://pr0gramm.com/\",\n    \"urlProbe\": \"https://pr0gramm.com/api/profile/info?name={}\",\n    \"username_claimed\": \"cha0s\"\n  },\n  \"prog.hu\": {\n    \"errorType\": \"response_url\",\n    \"errorUrl\": \"https://prog.hu/azonosito/info/{}\",\n    \"url\": \"https://prog.hu/azonosito/info/{}\",\n    \"urlMain\": \"https://prog.hu/\",\n    \"username_claimed\": \"Sting\"\n  },\n  \"satsisRU\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://satsis.info/user/{}\",\n    \"urlMain\": \"https://satsis.info/\",\n    \"username_claimed\": \"red\"\n  },\n  \"sessionize\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://sessionize.com/{}\",\n    \"urlMain\": \"https://sessionize.com/\",\n    \"username_claimed\": \"jason-mayes\"\n  },\n  \"social.tchncs.de\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://social.tchncs.de/@{}\",\n    \"urlMain\": \"https://social.tchncs.de/\",\n    \"username_claimed\": \"Milan\"\n  },\n  \"spletnik\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://spletnik.ru/user/{}\",\n    \"urlMain\": \"https://spletnik.ru/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"svidbook\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.svidbook.ru/user/{}\",\n    \"urlMain\": \"https://www.svidbook.ru/\",\n    \"username_claimed\": \"green\"\n  },\n  \"threads\": {\n    \"errorMsg\": \"<title>Threads • Log in</title>\",\n    \"errorType\": \"message\",\n    \"headers\": {\n      \"Sec-Fetch-Mode\": \"navigate\"\n    },\n    \"url\": \"https://www.threads.net/@{}\",\n    \"urlMain\": \"https://www.threads.net/\",\n    \"username_claimed\": \"zuck\"\n  },\n  \"toster\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.toster.ru/user/{}/answers\",\n    \"urlMain\": \"https://www.toster.ru/\",\n    \"username_claimed\": \"adam\"\n  },\n  \"tumblr\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://{}.tumblr.com/\",\n    \"urlMain\": \"https://www.tumblr.com/\",\n    \"username_claimed\": \"goku\"\n  },\n  \"uid\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"http://uid.me/{}\",\n    \"urlMain\": \"https://uid.me/\",\n    \"username_claimed\": \"blue\"\n  },\n  \"write.as\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://write.as/{}\",\n    \"urlMain\": \"https://write.as\",\n    \"username_claimed\": \"pylapp\"\n  },\n  \"xHamster\": {\n    \"errorType\": \"status_code\",\n    \"isNSFW\": true,\n    \"url\": \"https://xhamster.com/users/{}\",\n    \"urlMain\": \"https://xhamster.com\",\n    \"urlProbe\": \"https://xhamster.com/users/{}?old_browser=true\",\n    \"username_claimed\": \"blue\"\n  },\n  \"znanylekarz.pl\": {\n    \"errorType\": \"status_code\",\n    \"url\": \"https://www.znanylekarz.pl/{}\",\n    \"urlMain\": \"https://znanylekarz.pl\",\n    \"username_claimed\": \"janusz-nowak\"\n  },\n  \"Platzi\": {\n    \"errorType\": \"status_code\",\n    \"errorCode\": 404,\n    \"url\": \"https://platzi.com/p/{}/\",\n    \"urlMain\": \"https://platzi.com/\",\n    \"username_claimed\": \"freddier\",\n    \"request_method\": \"GET\"\n  },\n  \"BabyRu\": {\n    \"url\": \"https://www.baby.ru/u/{}\",\n    \"urlMain\": \"https://www.baby.ru/\",\n    \"errorType\": \"message\",\n    \"errorMsg\": [\n      \"\\u0421\\u0442\\u0440\\u0430\\u043d\\u0438\\u0446\\u0430, \\u043a\\u043e\\u0442\\u043e\\u0440\\u0443\\u044e \\u0432\\u044b \\u0438\\u0441\\u043a\\u0430\\u043b\\u0438, \\u043d\\u0435 \\u043d\\u0430\\u0439\\u0434\\u0435\\u043d\\u0430\",\n      \"\\u0414\\u043e\\u0441\\u0442\\u0443\\u043f \\u0441 \\u0432\\u0430\\u0448\\u0435\\u0433\\u043e IP-\\u0430\\u0434\\u0440\\u0435\\u0441\\u0430 \\u0432\\u0440\\u0435\\u043c\\u0435\\u043d\\u043d\\u043e \\u043e\\u0433\\u0440\\u0430\\u043d\\u0438\\u0447\\u0435\\u043d\"\n    ],\n    \"username_claimed\": \"example\"\n  },\n  \"Wowhead\": {\n    \"url\": \"https://wowhead.com/user={}\",\n    \"urlMain\": \"https://wowhead.com/\",\n    \"errorType\": \"status_code\",\n    \"errorCode\": 404,\n    \"username_claimed\": \"blue\"\n  },\n  \"addons.wago.io\": {\n    \"url\": \"https://addons.wago.io/user/{}\",\n    \"urlMain\": \"https://addons.wago.io/\",\n    \"errorType\": \"status_code\",\n    \"errorCode\": 404,\n    \"username_claimed\": \"blue\"\n  },\n  \"CurseForge\": {\n    \"url\": \"https://www.curseforge.com/members/{}/projects\",\n    \"urlMain\": \"https://www.curseforge.com.\",\n    \"errorType\": \"status_code\",\n    \"errorCode\": 404,\n    \"username_claimed\": \"blue\"\n  }\n}\n"
  },
  {
    "path": "sherlock_project/resources/data.schema.json",
    "content": "{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"title\": \"Sherlock Target Manifest\",\n  \"description\": \"Social media targets to probe for the existence of known usernames\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"$schema\": { \"type\": \"string\" }\n  },\n  \"patternProperties\": {\n    \"^(?!\\\\$).*?$\": {\n      \"type\": \"object\",\n      \"description\": \"Target name and associated information (key should be human readable name)\",\n      \"required\": [\"url\", \"urlMain\", \"errorType\", \"username_claimed\"],\n      \"properties\": {\n        \"url\": { \"type\": \"string\" },\n        \"urlMain\": { \"type\": \"string\" },\n        \"urlProbe\": { \"type\": \"string\" },\n        \"username_claimed\": { \"type\": \"string\" },\n        \"regexCheck\": { \"type\": \"string\" },\n        \"isNSFW\": { \"type\": \"boolean\" },\n        \"headers\": { \"type\": \"object\" },\n        \"request_payload\": { \"type\": \"object\" },\n        \"__comment__\": {\n          \"type\": \"string\",\n          \"description\": \"Used to clarify important target information if (and only if) a commit message would not suffice.\\nThis key should not be parsed anywhere within Sherlock.\"\n        },\n        \"tags\": {\n          \"oneOf\": [\n            { \"$ref\": \"#/$defs/tag\" },\n            { \"type\": \"array\", \"items\": { \"$ref\": \"#/$defs/tag\" } }\n          ]\n        },\n        \"request_method\": {\n          \"type\": \"string\",\n          \"enum\": [\"GET\", \"POST\", \"HEAD\", \"PUT\"]\n        },\n        \"errorType\": {\n          \"oneOf\": [\n            {\n              \"type\": \"string\",\n              \"enum\": [\"message\", \"response_url\", \"status_code\"]\n            },\n            {\n              \"type\": \"array\",\n              \"items\": {\n                \"type\": \"string\",\n                \"enum\": [\"message\", \"response_url\", \"status_code\"]\n              }\n            }\n          ]\n        },\n        \"errorMsg\": {\n          \"oneOf\": [\n            { \"type\": \"string\" },\n            { \"type\": \"array\", \"items\": { \"type\": \"string\" } }\n          ]\n        },\n        \"errorCode\": {\n          \"oneOf\": [\n            { \"type\": \"integer\" },\n            { \"type\": \"array\", \"items\": { \"type\": \"integer\" } }\n          ]\n        },\n        \"errorUrl\": { \"type\": \"string\" },\n        \"response_url\": { \"type\": \"string\" }\n      },\n      \"dependencies\": {\n        \"errorMsg\": {\n          \"oneOf\": [\n            { \"properties\": { \"errorType\": { \"const\": \"message\" } } },\n            {\n              \"properties\": {\n                \"errorType\": {\n                  \"type\": \"array\",\n                  \"contains\": { \"const\": \"message\" }\n                }\n              }\n            }\n          ]\n        },\n        \"errorUrl\": {\n          \"oneOf\": [\n            { \"properties\": { \"errorType\": { \"const\": \"response_url\" } } },\n            {\n              \"properties\": {\n                \"errorType\": {\n                  \"type\": \"array\",\n                  \"contains\": { \"const\": \"response_url\" }\n                }\n              }\n            }\n          ]\n        },\n        \"errorCode\": {\n          \"oneOf\": [\n            { \"properties\": { \"errorType\": { \"const\": \"status_code\" } } },\n            {\n              \"properties\": {\n                \"errorType\": {\n                  \"type\": \"array\",\n                  \"contains\": { \"const\": \"status_code\" }\n                }\n              }\n            }\n          ]\n        }\n      },\n      \"allOf\": [\n        {\n          \"if\": {\n            \"anyOf\": [\n              { \"properties\": { \"errorType\": { \"const\": \"message\" } } },\n              {\n                \"properties\": {\n                  \"errorType\": {\n                    \"type\": \"array\",\n                    \"contains\": { \"const\": \"message\" }\n                  }\n                }\n              }\n            ]\n          },\n          \"then\": { \"required\": [\"errorMsg\"] }\n        },\n        {\n          \"if\": {\n            \"anyOf\": [\n              { \"properties\": { \"errorType\": { \"const\": \"response_url\" } } },\n              {\n                \"properties\": {\n                  \"errorType\": {\n                    \"type\": \"array\",\n                    \"contains\": { \"const\": \"response_url\" }\n                  }\n                }\n              }\n            ]\n          },\n          \"then\": { \"required\": [\"errorUrl\"] }\n        }\n      ],\n      \"additionalProperties\": false\n    }\n  },\n  \"additionalProperties\": false,\n  \"$defs\": {\n    \"tag\": { \"type\": \"string\", \"enum\": [\"adult\", \"gaming\"] }\n  }\n}\n"
  },
  {
    "path": "sherlock_project/result.py",
    "content": "\"\"\"Sherlock Result Module\n\nThis module defines various objects for recording the results of queries.\n\"\"\"\nfrom enum import Enum\n\n\nclass QueryStatus(Enum):\n    \"\"\"Query Status Enumeration.\n\n    Describes status of query about a given username.\n    \"\"\"\n    CLAIMED   = \"Claimed\"   # Username Detected\n    AVAILABLE = \"Available\" # Username Not Detected\n    UNKNOWN   = \"Unknown\"   # Error Occurred While Trying To Detect Username\n    ILLEGAL   = \"Illegal\"   # Username Not Allowable For This Site\n    WAF       = \"WAF\"       # Request blocked by WAF (i.e. Cloudflare)\n\n    def __str__(self):\n        \"\"\"Convert Object To String.\n\n        Keyword Arguments:\n        self                   -- This object.\n\n        Return Value:\n        Nicely formatted string to get information about this object.\n        \"\"\"\n        return self.value\n\nclass QueryResult():\n    \"\"\"Query Result Object.\n\n    Describes result of query about a given username.\n    \"\"\"\n    def __init__(self, username, site_name, site_url_user, status,\n                 query_time=None, context=None):\n        \"\"\"Create Query Result Object.\n\n        Contains information about a specific method of detecting usernames on\n        a given type of web sites.\n\n        Keyword Arguments:\n        self                   -- This object.\n        username               -- String indicating username that query result\n                                  was about.\n        site_name              -- String which identifies site.\n        site_url_user          -- String containing URL for username on site.\n                                  NOTE:  The site may or may not exist:  this\n                                         just indicates what the name would\n                                         be, if it existed.\n        status                 -- Enumeration of type QueryStatus() indicating\n                                  the status of the query.\n        query_time             -- Time (in seconds) required to perform query.\n                                  Default of None.\n        context                -- String indicating any additional context\n                                  about the query.  For example, if there was\n                                  an error, this might indicate the type of\n                                  error that occurred.\n                                  Default of None.\n\n        Return Value:\n        Nothing.\n        \"\"\"\n\n        self.username      = username\n        self.site_name     = site_name\n        self.site_url_user = site_url_user\n        self.status        = status\n        self.query_time    = query_time\n        self.context       = context\n\n        return\n\n    def __str__(self):\n        \"\"\"Convert Object To String.\n\n        Keyword Arguments:\n        self                   -- This object.\n\n        Return Value:\n        Nicely formatted string to get information about this object.\n        \"\"\"\n        status = str(self.status)\n        if self.context is not None:\n            # There is extra context information available about the results.\n            # Append it to the normal response text.\n            status += f\" ({self.context})\"\n\n        return status\n"
  },
  {
    "path": "sherlock_project/sherlock.py",
    "content": "#! /usr/bin/env python3\n\n\"\"\"\nSherlock: Find Usernames Across Social Networks Module\n\nThis module contains the main logic to search for usernames at social\nnetworks.\n\"\"\"\n\nimport sys\n\ntry:\n    from sherlock_project.__init__ import import_error_test_var # noqa: F401\nexcept ImportError:\n    print(\"Did you run Sherlock with `python3 sherlock/sherlock.py ...`?\")\n    print(\"This is an outdated method. Please see https://sherlockproject.xyz/installation for up to date instructions.\")\n    sys.exit(1)\n\nimport csv\nimport signal\nimport pandas as pd\nimport os\nimport re\nfrom argparse import ArgumentParser, RawDescriptionHelpFormatter\nfrom json import loads as json_loads\nfrom time import monotonic\nfrom typing import Optional\n\nimport requests\nfrom requests_futures.sessions import FuturesSession\n\nfrom sherlock_project.__init__ import (\n    __longname__,\n    __shortname__,\n    __version__,\n    forge_api_latest_release,\n)\n\nfrom sherlock_project.result import QueryStatus\nfrom sherlock_project.result import QueryResult\nfrom sherlock_project.notify import QueryNotify\nfrom sherlock_project.notify import QueryNotifyPrint\nfrom sherlock_project.sites import SitesInformation\nfrom colorama import init\nfrom argparse import ArgumentTypeError\n\n\nclass SherlockFuturesSession(FuturesSession):\n    def request(self, method, url, hooks=None, *args, **kwargs):\n        \"\"\"Request URL.\n\n        This extends the FuturesSession request method to calculate a response\n        time metric to each request.\n\n        It is taken (almost) directly from the following Stack Overflow answer:\n        https://github.com/ross/requests-futures#working-in-the-background\n\n        Keyword Arguments:\n        self                   -- This object.\n        method                 -- String containing method desired for request.\n        url                    -- String containing URL for request.\n        hooks                  -- Dictionary containing hooks to execute after\n                                  request finishes.\n        args                   -- Arguments.\n        kwargs                 -- Keyword arguments.\n\n        Return Value:\n        Request object.\n        \"\"\"\n        # Record the start time for the request.\n        if hooks is None:\n            hooks = {}\n        start = monotonic()\n\n        def response_time(resp, *args, **kwargs):\n            \"\"\"Response Time Hook.\n\n            Keyword Arguments:\n            resp                   -- Response object.\n            args                   -- Arguments.\n            kwargs                 -- Keyword arguments.\n\n            Return Value:\n            Nothing.\n            \"\"\"\n            resp.elapsed = monotonic() - start\n\n            return\n\n        # Install hook to execute when response completes.\n        # Make sure that the time measurement hook is first, so we will not\n        # track any later hook's execution time.\n        try:\n            if isinstance(hooks[\"response\"], list):\n                hooks[\"response\"].insert(0, response_time)\n            elif isinstance(hooks[\"response\"], tuple):\n                # Convert tuple to list and insert time measurement hook first.\n                hooks[\"response\"] = list(hooks[\"response\"])\n                hooks[\"response\"].insert(0, response_time)\n            else:\n                # Must have previously contained a single hook function,\n                # so convert to list.\n                hooks[\"response\"] = [response_time, hooks[\"response\"]]\n        except KeyError:\n            # No response hook was already defined, so install it ourselves.\n            hooks[\"response\"] = [response_time]\n\n        return super(SherlockFuturesSession, self).request(\n            method, url, hooks=hooks, *args, **kwargs\n        )\n\n\ndef get_response(request_future, error_type, social_network):\n    # Default for Response object if some failure occurs.\n    response = None\n\n    error_context = \"General Unknown Error\"\n    exception_text = None\n    try:\n        response = request_future.result()\n        if response.status_code:\n            # Status code exists in response object\n            error_context = None\n    except requests.exceptions.HTTPError as errh:\n        error_context = \"HTTP Error\"\n        exception_text = str(errh)\n    except requests.exceptions.ProxyError as errp:\n        error_context = \"Proxy Error\"\n        exception_text = str(errp)\n    except requests.exceptions.ConnectionError as errc:\n        error_context = \"Error Connecting\"\n        exception_text = str(errc)\n    except requests.exceptions.Timeout as errt:\n        error_context = \"Timeout Error\"\n        exception_text = str(errt)\n    except requests.exceptions.RequestException as err:\n        error_context = \"Unknown Error\"\n        exception_text = str(err)\n\n    return response, error_context, exception_text\n\n\ndef interpolate_string(input_object, username):\n    if isinstance(input_object, str):\n        return input_object.replace(\"{}\", username)\n    elif isinstance(input_object, dict):\n        return {k: interpolate_string(v, username) for k, v in input_object.items()}\n    elif isinstance(input_object, list):\n        return [interpolate_string(i, username) for i in input_object]\n    return input_object\n\n\ndef check_for_parameter(username):\n    \"\"\"checks if {?} exists in the username\n    if exist it means that sherlock is looking for more multiple username\"\"\"\n    return \"{?}\" in username\n\n\nchecksymbols = [\"_\", \"-\", \".\"]\n\n\ndef multiple_usernames(username):\n    \"\"\"replace the parameter with with symbols and return a list of usernames\"\"\"\n    allUsernames = []\n    for i in checksymbols:\n        allUsernames.append(username.replace(\"{?}\", i))\n    return allUsernames\n\n\ndef sherlock(\n    username: str,\n    site_data: dict[str, dict[str, str]],\n    query_notify: QueryNotify,\n    dump_response: bool = False,\n    proxy: Optional[str] = None,\n    timeout: int = 60,\n) -> dict[str, dict[str, str | QueryResult]]:\n    \"\"\"Run Sherlock Analysis.\n\n    Checks for existence of username on various social media sites.\n\n    Keyword Arguments:\n    username               -- String indicating username that report\n                              should be created against.\n    site_data              -- Dictionary containing all of the site data.\n    query_notify           -- Object with base type of QueryNotify().\n                              This will be used to notify the caller about\n                              query results.\n    proxy                  -- String indicating the proxy URL\n    timeout                -- Time in seconds to wait before timing out request.\n                              Default is 60 seconds.\n\n    Return Value:\n    Dictionary containing results from report. Key of dictionary is the name\n    of the social network site, and the value is another dictionary with\n    the following keys:\n        url_main:      URL of main site.\n        url_user:      URL of user on site (if account exists).\n        status:        QueryResult() object indicating results of test for\n                       account existence.\n        http_status:   HTTP status code of query which checked for existence on\n                       site.\n        response_text: Text that came back from request.  May be None if\n                       there was an HTTP error when checking for existence.\n    \"\"\"\n\n    # Notify caller that we are starting the query.\n    query_notify.start(username)\n\n    # Normal requests\n    underlying_session = requests.session()\n\n    # Limit number of workers to 20.\n    # This is probably vastly overkill.\n    if len(site_data) >= 20:\n        max_workers = 20\n    else:\n        max_workers = len(site_data)\n\n    # Create multi-threaded session for all requests.\n    session = SherlockFuturesSession(\n        max_workers=max_workers, session=underlying_session\n    )\n\n    # Results from analysis of all sites\n    results_total = {}\n\n    # First create futures for all requests. This allows for the requests to run in parallel\n    for social_network, net_info in site_data.items():\n        # Results from analysis of this specific site\n        results_site = {\"url_main\": net_info.get(\"urlMain\")}\n\n        # Record URL of main site\n\n        # A user agent is needed because some sites don't return the correct\n        # information since they think that we are bots (Which we actually are...)\n        headers = {\n            \"User-Agent\": \"Mozilla/5.0 (X11; Linux x86_64; rv:129.0) Gecko/20100101 Firefox/129.0\",\n        }\n\n        if \"headers\" in net_info:\n            # Override/append any extra headers required by a given site.\n            headers.update(net_info[\"headers\"])\n\n        # URL of user on site (if it exists)\n        url = interpolate_string(net_info[\"url\"], username.replace(' ', '%20'))\n\n        # Don't make request if username is invalid for the site\n        regex_check = net_info.get(\"regexCheck\")\n        if regex_check and re.search(regex_check, username) is None:\n            # No need to do the check at the site: this username is not allowed.\n            results_site[\"status\"] = QueryResult(\n                username, social_network, url, QueryStatus.ILLEGAL\n            )\n            results_site[\"url_user\"] = \"\"\n            results_site[\"http_status\"] = \"\"\n            results_site[\"response_text\"] = \"\"\n            query_notify.update(results_site[\"status\"])\n        else:\n            # URL of user on site (if it exists)\n            results_site[\"url_user\"] = url\n            url_probe = net_info.get(\"urlProbe\")\n            request_method = net_info.get(\"request_method\")\n            request_payload = net_info.get(\"request_payload\")\n            request = None\n\n            if request_method is not None:\n                if request_method == \"GET\":\n                    request = session.get\n                elif request_method == \"HEAD\":\n                    request = session.head\n                elif request_method == \"POST\":\n                    request = session.post\n                elif request_method == \"PUT\":\n                    request = session.put\n                else:\n                    raise RuntimeError(f\"Unsupported request_method for {url}\")\n\n            if request_payload is not None:\n                request_payload = interpolate_string(request_payload, username)\n\n            if url_probe is None:\n                # Probe URL is normal one seen by people out on the web.\n                url_probe = url\n            else:\n                # There is a special URL for probing existence separate\n                # from where the user profile normally can be found.\n                url_probe = interpolate_string(url_probe, username)\n\n            if request is None:\n                if net_info[\"errorType\"] == \"status_code\":\n                    # In most cases when we are detecting by status code,\n                    # it is not necessary to get the entire body:  we can\n                    # detect fine with just the HEAD response.\n                    request = session.head\n                else:\n                    # Either this detect method needs the content associated\n                    # with the GET response, or this specific website will\n                    # not respond properly unless we request the whole page.\n                    request = session.get\n\n            if net_info[\"errorType\"] == \"response_url\":\n                # Site forwards request to a different URL if username not\n                # found.  Disallow the redirect so we can capture the\n                # http status from the original URL request.\n                allow_redirects = False\n            else:\n                # Allow whatever redirect that the site wants to do.\n                # The final result of the request will be what is available.\n                allow_redirects = True\n\n            # This future starts running the request in a new thread, doesn't block the main thread\n            if proxy is not None:\n                proxies = {\"http\": proxy, \"https\": proxy}\n                future = request(\n                    url=url_probe,\n                    headers=headers,\n                    proxies=proxies,\n                    allow_redirects=allow_redirects,\n                    timeout=timeout,\n                    json=request_payload,\n                )\n            else:\n                future = request(\n                    url=url_probe,\n                    headers=headers,\n                    allow_redirects=allow_redirects,\n                    timeout=timeout,\n                    json=request_payload,\n                )\n\n            # Store future in data for access later\n            net_info[\"request_future\"] = future\n\n        # Add this site's results into final dictionary with all the other results.\n        results_total[social_network] = results_site\n\n    # Open the file containing account links\n    for social_network, net_info in site_data.items():\n        # Retrieve results again\n        results_site = results_total.get(social_network)\n\n        # Retrieve other site information again\n        url = results_site.get(\"url_user\")\n        status = results_site.get(\"status\")\n        if status is not None:\n            # We have already determined the user doesn't exist here\n            continue\n\n        # Get the expected error type\n        error_type = net_info[\"errorType\"]\n        if isinstance(error_type, str):\n            error_type: list[str] = [error_type]\n\n        # Retrieve future and ensure it has finished\n        future = net_info[\"request_future\"]\n        r, error_text, exception_text = get_response(\n            request_future=future, error_type=error_type, social_network=social_network\n        )\n\n        # Get response time for response of our request.\n        try:\n            response_time = r.elapsed\n        except AttributeError:\n            response_time = None\n\n        # Attempt to get request information\n        try:\n            http_status = r.status_code\n        except Exception:\n            http_status = \"?\"\n        try:\n            response_text = r.text.encode(r.encoding or \"UTF-8\")\n        except Exception:\n            response_text = \"\"\n\n        query_status = QueryStatus.UNKNOWN\n        error_context = None\n\n        # As WAFs advance and evolve, they will occasionally block Sherlock and\n        # lead to false positives and negatives. Fingerprints should be added\n        # here to filter results that fail to bypass WAFs. Fingerprints should\n        # be highly targetted. Comment at the end of each fingerprint to\n        # indicate target and date fingerprinted.\n        WAFHitMsgs = [\n            r'.loading-spinner{visibility:hidden}body.no-js .challenge-running{display:none}body.dark{background-color:#222;color:#d9d9d9}body.dark a{color:#fff}body.dark a:hover{color:#ee730a;text-decoration:underline}body.dark .lds-ring div{border-color:#999 transparent transparent}body.dark .font-red{color:#b20f03}body.dark', # 2024-05-13 Cloudflare\n            r'<span id=\"challenge-error-text\">', # 2024-11-11 Cloudflare error page\n            r'AwsWafIntegration.forceRefreshToken', # 2024-11-11 Cloudfront (AWS)\n            r'{return l.onPageView}}),Object.defineProperty(r,\"perimeterxIdentifiers\",{enumerable:' # 2024-04-09 PerimeterX / Human Security\n        ]\n\n        if error_text is not None:\n            error_context = error_text\n\n        elif any(hitMsg in r.text for hitMsg in WAFHitMsgs):\n            query_status = QueryStatus.WAF\n\n        else:\n            if any(errtype not in [\"message\", \"status_code\", \"response_url\"] for errtype in error_type):\n                error_context = f\"Unknown error type '{error_type}' for {social_network}\"\n                query_status = QueryStatus.UNKNOWN\n            else:\n                if \"message\" in error_type:\n                    # error_flag True denotes no error found in the HTML\n                    # error_flag False denotes error found in the HTML\n                    error_flag = True\n                    errors = net_info.get(\"errorMsg\")\n                    # errors will hold the error message\n                    # it can be string or list\n                    # by isinstance method we can detect that\n                    # and handle the case for strings as normal procedure\n                    # and if its list we can iterate the errors\n                    if isinstance(errors, str):\n                        # Checks if the error message is in the HTML\n                        # if error is present we will set flag to False\n                        if errors in r.text:\n                            error_flag = False\n                    else:\n                        # If it's list, it will iterate all the error message\n                        for error in errors:\n                            if error in r.text:\n                                error_flag = False\n                                break\n                    if error_flag:\n                        query_status = QueryStatus.CLAIMED\n                    else:\n                        query_status = QueryStatus.AVAILABLE\n\n                if \"status_code\" in error_type and query_status is not QueryStatus.AVAILABLE:\n                    error_codes = net_info.get(\"errorCode\")\n                    query_status = QueryStatus.CLAIMED\n\n                    # Type consistency, allowing for both singlets and lists in manifest\n                    if isinstance(error_codes, int):\n                        error_codes = [error_codes]\n\n                    if error_codes is not None and r.status_code in error_codes:\n                        query_status = QueryStatus.AVAILABLE\n                    elif r.status_code >= 300 or r.status_code < 200:\n                        query_status = QueryStatus.AVAILABLE\n\n                if \"response_url\" in error_type and query_status is not QueryStatus.AVAILABLE:\n                    # For this detection method, we have turned off the redirect.\n                    # So, there is no need to check the response URL: it will always\n                    # match the request.  Instead, we will ensure that the response\n                    # code indicates that the request was successful (i.e. no 404, or\n                    # forward to some odd redirect).\n                    if 200 <= r.status_code < 300:\n                        query_status = QueryStatus.CLAIMED\n                    else:\n                        query_status = QueryStatus.AVAILABLE\n\n        if dump_response:\n            print(\"+++++++++++++++++++++\")\n            print(f\"TARGET NAME   : {social_network}\")\n            print(f\"USERNAME      : {username}\")\n            print(f\"TARGET URL    : {url}\")\n            print(f\"TEST METHOD   : {error_type}\")\n            try:\n                print(f\"STATUS CODES  : {net_info['errorCode']}\")\n            except KeyError:\n                pass\n            print(\"Results...\")\n            try:\n                print(f\"RESPONSE CODE : {r.status_code}\")\n            except Exception:\n                pass\n            try:\n                print(f\"ERROR TEXT    : {net_info['errorMsg']}\")\n            except KeyError:\n                pass\n            print(\">>>>> BEGIN RESPONSE TEXT\")\n            try:\n                print(r.text)\n            except Exception:\n                pass\n            print(\"<<<<< END RESPONSE TEXT\")\n            print(\"VERDICT       : \" + str(query_status))\n            print(\"+++++++++++++++++++++\")\n\n        # Notify caller about results of query.\n        result: QueryResult = QueryResult(\n            username=username,\n            site_name=social_network,\n            site_url_user=url,\n            status=query_status,\n            query_time=response_time,\n            context=error_context,\n        )\n        query_notify.update(result)\n\n        # Save status of request\n        results_site[\"status\"] = result\n\n        # Save results from request\n        results_site[\"http_status\"] = http_status\n        results_site[\"response_text\"] = response_text\n\n        # Add this site's results into final dictionary with all of the other results.\n        results_total[social_network] = results_site\n\n    return results_total\n\n\ndef timeout_check(value):\n    \"\"\"Check Timeout Argument.\n\n    Checks timeout for validity.\n\n    Keyword Arguments:\n    value                  -- Time in seconds to wait before timing out request.\n\n    Return Value:\n    Floating point number representing the time (in seconds) that should be\n    used for the timeout.\n\n    NOTE:  Will raise an exception if the timeout in invalid.\n    \"\"\"\n\n    float_value = float(value)\n\n    if float_value <= 0:\n        raise ArgumentTypeError(\n            f\"Invalid timeout value: {value}. Timeout must be a positive number.\"\n        )\n\n    return float_value\n\n\ndef handler(signal_received, frame):\n    \"\"\"Exit gracefully without throwing errors\n\n    Source: https://www.devdungeon.com/content/python-catch-sigint-ctrl-c\n    \"\"\"\n    sys.exit(0)\n\n\ndef main():\n    parser = ArgumentParser(\n        formatter_class=RawDescriptionHelpFormatter,\n        description=f\"{__longname__} (Version {__version__})\",\n    )\n    parser.add_argument(\n        \"--version\",\n        action=\"version\",\n        version=f\"{__shortname__} v{__version__}\",\n        help=\"Display version information and dependencies.\",\n    )\n    parser.add_argument(\n        \"--verbose\",\n        \"-v\",\n        \"-d\",\n        \"--debug\",\n        action=\"store_true\",\n        dest=\"verbose\",\n        default=False,\n        help=\"Display extra debugging information and metrics.\",\n    )\n    parser.add_argument(\n        \"--folderoutput\",\n        \"-fo\",\n        dest=\"folderoutput\",\n        help=\"If using multiple usernames, the output of the results will be saved to this folder.\",\n    )\n    parser.add_argument(\n        \"--output\",\n        \"-o\",\n        dest=\"output\",\n        help=\"If using single username, the output of the result will be saved to this file.\",\n    )\n    parser.add_argument(\n        \"--csv\",\n        action=\"store_true\",\n        dest=\"csv\",\n        default=False,\n        help=\"Create Comma-Separated Values (CSV) File.\",\n    )\n    parser.add_argument(\n        \"--xlsx\",\n        action=\"store_true\",\n        dest=\"xlsx\",\n        default=False,\n        help=\"Create the standard file for the modern Microsoft Excel spreadsheet (xlsx).\",\n    )\n    parser.add_argument(\n        \"--site\",\n        action=\"append\",\n        metavar=\"SITE_NAME\",\n        dest=\"site_list\",\n        default=[],\n        help=\"Limit analysis to just the listed sites. Add multiple options to specify more than one site.\",\n    )\n    parser.add_argument(\n        \"--proxy\",\n        \"-p\",\n        metavar=\"PROXY_URL\",\n        action=\"store\",\n        dest=\"proxy\",\n        default=None,\n        help=\"Make requests over a proxy. e.g. socks5://127.0.0.1:1080\",\n    )\n    parser.add_argument(\n        \"--dump-response\",\n        action=\"store_true\",\n        dest=\"dump_response\",\n        default=False,\n        help=\"Dump the HTTP response to stdout for targeted debugging.\",\n    )\n    parser.add_argument(\n        \"--json\",\n        \"-j\",\n        metavar=\"JSON_FILE\",\n        dest=\"json_file\",\n        default=None,\n        help=\"Load data from a JSON file or an online, valid, JSON file. Upstream PR numbers also accepted.\",\n    )\n    parser.add_argument(\n        \"--timeout\",\n        action=\"store\",\n        metavar=\"TIMEOUT\",\n        dest=\"timeout\",\n        type=timeout_check,\n        default=60,\n        help=\"Time (in seconds) to wait for response to requests (Default: 60)\",\n    )\n    parser.add_argument(\n        \"--print-all\",\n        action=\"store_true\",\n        dest=\"print_all\",\n        default=False,\n        help=\"Output sites where the username was not found.\",\n    )\n    parser.add_argument(\n        \"--print-found\",\n        action=\"store_true\",\n        dest=\"print_found\",\n        default=True,\n        help=\"Output sites where the username was found (also if exported as file).\",\n    )\n    parser.add_argument(\n        \"--no-color\",\n        action=\"store_true\",\n        dest=\"no_color\",\n        default=False,\n        help=\"Don't color terminal output\",\n    )\n    parser.add_argument(\n        \"username\",\n        nargs=\"+\",\n        metavar=\"USERNAMES\",\n        action=\"store\",\n        help=\"One or more usernames to check with social networks. Check similar usernames using {?} (replace to '_', '-', '.').\",\n    )\n    parser.add_argument(\n        \"--browse\",\n        \"-b\",\n        action=\"store_true\",\n        dest=\"browse\",\n        default=False,\n        help=\"Browse to all results on default browser.\",\n    )\n\n    parser.add_argument(\n        \"--local\",\n        \"-l\",\n        action=\"store_true\",\n        default=False,\n        help=\"Force the use of the local data.json file.\",\n    )\n\n    parser.add_argument(\n        \"--nsfw\",\n        action=\"store_true\",\n        default=False,\n        help=\"Include checking of NSFW sites from default list.\",\n    )\n\n    # TODO deprecated in favor of --txt, retained for workflow compatibility, to be removed\n    # in future release\n    parser.add_argument(\n        \"--no-txt\",\n        action=\"store_true\",\n        dest=\"no_txt\",\n        default=False,\n        help=\"Disable creation of a txt file - WILL BE DEPRECATED\",\n    )\n\n    parser.add_argument(\n        \"--txt\",\n        action=\"store_true\",\n        dest=\"output_txt\",\n        default=False,\n        help=\"Enable creation of a txt file\",\n    )\n\n    parser.add_argument(\n        \"--ignore-exclusions\",\n        action=\"store_true\",\n        dest=\"ignore_exclusions\",\n        default=False,\n        help=\"Ignore upstream exclusions (may return more false positives)\",\n    )\n\n    args = parser.parse_args()\n\n    # If the user presses CTRL-C, exit gracefully without throwing errors\n    signal.signal(signal.SIGINT, handler)\n\n    # Check for newer version of Sherlock. If it exists, let the user know about it\n    try:\n        latest_release_raw = requests.get(forge_api_latest_release, timeout=10).text\n        latest_release_json = json_loads(latest_release_raw)\n        latest_remote_tag = latest_release_json[\"tag_name\"]\n\n        if latest_remote_tag[1:] != __version__:\n            print(\n                f\"Update available! {__version__} --> {latest_remote_tag[1:]}\"\n                f\"\\n{latest_release_json['html_url']}\"\n            )\n\n    except Exception as error:\n        print(f\"A problem occurred while checking for an update: {error}\")\n\n    # Make prompts\n    if args.proxy is not None:\n        print(\"Using the proxy: \" + args.proxy)\n\n    if args.no_color:\n        # Disable color output.\n        init(strip=True, convert=False)\n    else:\n        # Enable color output.\n        init(autoreset=True)\n\n    # Check if both output methods are entered as input.\n    if args.output is not None and args.folderoutput is not None:\n        print(\"You can only use one of the output methods.\")\n        sys.exit(1)\n\n    # Check validity for single username output.\n    if args.output is not None and len(args.username) != 1:\n        print(\"You can only use --output with a single username\")\n        sys.exit(1)\n\n    # Create object with all information about sites we are aware of.\n    try:\n        if args.local:\n            sites = SitesInformation(\n                os.path.join(os.path.dirname(__file__), \"resources/data.json\"),\n                honor_exclusions=False,\n            )\n        else:\n            json_file_location = args.json_file\n            if args.json_file:\n                # If --json parameter is a number, interpret it as a pull request number\n                if args.json_file.isnumeric():\n                    pull_number = args.json_file\n                    pull_url = f\"https://api.github.com/repos/sherlock-project/sherlock/pulls/{pull_number}\"\n                    pull_request_raw = requests.get(pull_url, timeout=10).text\n                    pull_request_json = json_loads(pull_request_raw)\n\n                    # Check if it's a valid pull request\n                    if \"message\" in pull_request_json:\n                        print(f\"ERROR: Pull request #{pull_number} not found.\")\n                        sys.exit(1)\n\n                    head_commit_sha = pull_request_json[\"head\"][\"sha\"]\n                    json_file_location = f\"https://raw.githubusercontent.com/sherlock-project/sherlock/{head_commit_sha}/sherlock_project/resources/data.json\"\n\n            sites = SitesInformation(\n                data_file_path=json_file_location,\n                honor_exclusions=not args.ignore_exclusions,\n                do_not_exclude=args.site_list,\n            )\n    except Exception as error:\n        print(f\"ERROR:  {error}\")\n        sys.exit(1)\n\n    if not args.nsfw:\n        sites.remove_nsfw_sites(do_not_remove=args.site_list)\n\n    # Create original dictionary from SitesInformation() object.\n    # Eventually, the rest of the code will be updated to use the new object\n    # directly, but this will glue the two pieces together.\n    site_data_all = {site.name: site.information for site in sites}\n    if args.site_list == []:\n        # Not desired to look at a sub-set of sites\n        site_data = site_data_all\n    else:\n        # User desires to selectively run queries on a sub-set of the site list.\n        # Make sure that the sites are supported & build up pruned site database.\n        site_data = {}\n        site_missing = []\n        for site in args.site_list:\n            counter = 0\n            for existing_site in site_data_all:\n                if site.lower() == existing_site.lower():\n                    site_data[existing_site] = site_data_all[existing_site]\n                    counter += 1\n            if counter == 0:\n                # Build up list of sites not supported for future error message.\n                site_missing.append(f\"'{site}'\")\n\n        if site_missing:\n            print(f\"Error: Desired sites not found: {', '.join(site_missing)}.\")\n\n        if not site_data:\n            sys.exit(1)\n\n    # Create notify object for query results.\n    query_notify = QueryNotifyPrint(\n        result=None, verbose=args.verbose, print_all=args.print_all, browse=args.browse\n    )\n\n    # Run report on all specified users.\n    all_usernames = []\n    for username in args.username:\n        if check_for_parameter(username):\n            for name in multiple_usernames(username):\n                all_usernames.append(name)\n        else:\n            all_usernames.append(username)\n    for username in all_usernames:\n        results = sherlock(\n            username,\n            site_data,\n            query_notify,\n            dump_response=args.dump_response,\n            proxy=args.proxy,\n            timeout=args.timeout,\n        )\n\n        if args.output:\n            result_file = args.output\n        elif args.folderoutput:\n            # The usernames results should be stored in a targeted folder.\n            # If the folder doesn't exist, create it first\n            os.makedirs(args.folderoutput, exist_ok=True)\n            result_file = os.path.join(args.folderoutput, f\"{username}.txt\")\n        else:\n            result_file = f\"{username}.txt\"\n\n        if args.output_txt:\n            with open(result_file, \"w\", encoding=\"utf-8\") as file:\n                exists_counter = 0\n                for website_name in results:\n                    dictionary = results[website_name]\n                    if dictionary.get(\"status\").status == QueryStatus.CLAIMED:\n                        exists_counter += 1\n                        file.write(dictionary[\"url_user\"] + \"\\n\")\n                file.write(f\"Total Websites Username Detected On : {exists_counter}\\n\")\n\n        if args.csv:\n            result_file = f\"{username}.csv\"\n            if args.folderoutput:\n                # The usernames results should be stored in a targeted folder.\n                # If the folder doesn't exist, create it first\n                os.makedirs(args.folderoutput, exist_ok=True)\n                result_file = os.path.join(args.folderoutput, result_file)\n\n            with open(result_file, \"w\", newline=\"\", encoding=\"utf-8\") as csv_report:\n                writer = csv.writer(csv_report)\n                writer.writerow(\n                    [\n                        \"username\",\n                        \"name\",\n                        \"url_main\",\n                        \"url_user\",\n                        \"exists\",\n                        \"http_status\",\n                        \"response_time_s\",\n                    ]\n                )\n                for site in results:\n                    if (\n                        args.print_found\n                        and not args.print_all\n                        and results[site][\"status\"].status != QueryStatus.CLAIMED\n                    ):\n                        continue\n\n                    response_time_s = results[site][\"status\"].query_time\n                    if response_time_s is None:\n                        response_time_s = \"\"\n                    writer.writerow(\n                        [\n                            username,\n                            site,\n                            results[site][\"url_main\"],\n                            results[site][\"url_user\"],\n                            str(results[site][\"status\"].status),\n                            results[site][\"http_status\"],\n                            response_time_s,\n                        ]\n                    )\n        if args.xlsx:\n            usernames = []\n            names = []\n            url_main = []\n            url_user = []\n            exists = []\n            http_status = []\n            response_time_s = []\n\n            for site in results:\n                if (\n                    args.print_found\n                    and not args.print_all\n                    and results[site][\"status\"].status != QueryStatus.CLAIMED\n                ):\n                    continue\n\n                if response_time_s is None:\n                    response_time_s.append(\"\")\n                else:\n                    response_time_s.append(results[site][\"status\"].query_time)\n                usernames.append(username)\n                names.append(site)\n                url_main.append(results[site][\"url_main\"])\n                url_user.append(results[site][\"url_user\"])\n                exists.append(str(results[site][\"status\"].status))\n                http_status.append(results[site][\"http_status\"])\n\n            DataFrame = pd.DataFrame(\n                {\n                    \"username\": usernames,\n                    \"name\": names,\n                    \"url_main\": [f'=HYPERLINK(\\\"{u}\\\")' for u in url_main],\n                    \"url_user\": [f'=HYPERLINK(\\\"{u}\\\")' for u in url_user],\n                    \"exists\": exists,\n                    \"http_status\": http_status,\n                    \"response_time_s\": response_time_s,\n                }\n            )\n            DataFrame.to_excel(f\"{username}.xlsx\", sheet_name=\"sheet1\", index=False)\n\n        print()\n    query_notify.finish()\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "sherlock_project/sites.py",
    "content": "\"\"\"Sherlock Sites Information Module\n\nThis module supports storing information about websites.\nThis is the raw data that will be used to search for usernames.\n\"\"\"\nimport json\nimport requests\nimport secrets\n\n\nMANIFEST_URL = \"https://raw.githubusercontent.com/sherlock-project/sherlock/master/sherlock_project/resources/data.json\"\nEXCLUSIONS_URL = \"https://raw.githubusercontent.com/sherlock-project/sherlock/refs/heads/exclusions/false_positive_exclusions.txt\"\n\nclass SiteInformation:\n    def __init__(self, name, url_home, url_username_format, username_claimed,\n                information, is_nsfw, username_unclaimed=secrets.token_urlsafe(10)):\n        \"\"\"Create Site Information Object.\n\n        Contains information about a specific website.\n\n        Keyword Arguments:\n        self                   -- This object.\n        name                   -- String which identifies site.\n        url_home               -- String containing URL for home of site.\n        url_username_format    -- String containing URL for Username format\n                                  on site.\n                                  NOTE:  The string should contain the\n                                         token \"{}\" where the username should\n                                         be substituted.  For example, a string\n                                         of \"https://somesite.com/users/{}\"\n                                         indicates that the individual\n                                         usernames would show up under the\n                                         \"https://somesite.com/users/\" area of\n                                         the website.\n        username_claimed       -- String containing username which is known\n                                  to be claimed on website.\n        username_unclaimed     -- String containing username which is known\n                                  to be unclaimed on website.\n        information            -- Dictionary containing all known information\n                                  about website.\n                                  NOTE:  Custom information about how to\n                                         actually detect the existence of the\n                                         username will be included in this\n                                         dictionary.  This information will\n                                         be needed by the detection method,\n                                         but it is only recorded in this\n                                         object for future use.\n        is_nsfw                -- Boolean indicating if site is Not Safe For Work.\n\n        Return Value:\n        Nothing.\n        \"\"\"\n\n        self.name = name\n        self.url_home = url_home\n        self.url_username_format = url_username_format\n\n        self.username_claimed = username_claimed\n        self.username_unclaimed = secrets.token_urlsafe(32)\n        self.information = information\n        self.is_nsfw  = is_nsfw\n\n        return\n\n    def __str__(self):\n        \"\"\"Convert Object To String.\n\n        Keyword Arguments:\n        self                   -- This object.\n\n        Return Value:\n        Nicely formatted string to get information about this object.\n        \"\"\"\n\n        return f\"{self.name} ({self.url_home})\"\n\n\nclass SitesInformation:\n    def __init__(\n            self,\n            data_file_path: str|None = None,\n            honor_exclusions: bool = True,\n            do_not_exclude: list[str] = [],\n        ):\n        \"\"\"Create Sites Information Object.\n\n        Contains information about all supported websites.\n\n        Keyword Arguments:\n        self                   -- This object.\n        data_file_path         -- String which indicates path to data file.\n                                  The file name must end in \".json\".\n\n                                  There are 3 possible formats:\n                                   * Absolute File Format\n                                     For example, \"c:/stuff/data.json\".\n                                   * Relative File Format\n                                     The current working directory is used\n                                     as the context.\n                                     For example, \"data.json\".\n                                   * URL Format\n                                     For example,\n                                     \"https://example.com/data.json\", or\n                                     \"http://example.com/data.json\".\n\n                                  An exception will be thrown if the path\n                                  to the data file is not in the expected\n                                  format, or if there was any problem loading\n                                  the file.\n\n                                  If this option is not specified, then a\n                                  default site list will be used.\n\n        Return Value:\n        Nothing.\n        \"\"\"\n\n        if not data_file_path:\n            # The default data file is the live data.json which is in the GitHub repo. The reason why we are using\n            # this instead of the local one is so that the user has the most up-to-date data. This prevents\n            # users from creating issue about false positives which has already been fixed or having outdated data\n            data_file_path = MANIFEST_URL\n\n        # Ensure that specified data file has correct extension.\n        if not data_file_path.lower().endswith(\".json\"):\n            raise FileNotFoundError(f\"Incorrect JSON file extension for data file '{data_file_path}'.\")\n\n        # if \"http://\"  == data_file_path[:7].lower() or \"https://\" == data_file_path[:8].lower():\n        if data_file_path.lower().startswith(\"http\"):\n            # Reference is to a URL.\n            try:\n                response = requests.get(url=data_file_path, timeout=30)\n            except Exception as error:\n                raise FileNotFoundError(\n                    f\"Problem while attempting to access data file URL '{data_file_path}':  {error}\"\n                )\n\n            if response.status_code != 200:\n                raise FileNotFoundError(f\"Bad response while accessing \"\n                                        f\"data file URL '{data_file_path}'.\"\n                                        )\n            try:\n                site_data = response.json()\n            except Exception as error:\n                raise ValueError(\n                    f\"Problem parsing json contents at '{data_file_path}':  {error}.\"\n                )\n\n        else:\n            # Reference is to a file.\n            try:\n                with open(data_file_path, \"r\", encoding=\"utf-8\") as file:\n                    try:\n                        site_data = json.load(file)\n                    except Exception as error:\n                        raise ValueError(\n                            f\"Problem parsing json contents at '{data_file_path}':  {error}.\"\n                        )\n\n            except FileNotFoundError:\n                raise FileNotFoundError(f\"Problem while attempting to access \"\n                                        f\"data file '{data_file_path}'.\"\n                                        )\n\n        site_data.pop('$schema', None)\n\n        if honor_exclusions:\n            try:\n                response = requests.get(url=EXCLUSIONS_URL, timeout=10)\n                if response.status_code == 200:\n                    exclusions = response.text.splitlines()\n                    exclusions = [exclusion.strip() for exclusion in exclusions]\n\n                    for site in do_not_exclude:\n                        if site in exclusions:\n                            exclusions.remove(site)\n\n                    for exclusion in exclusions:\n                        try:\n                            site_data.pop(exclusion, None)\n                        except KeyError:\n                            pass\n\n            except Exception:\n                # If there was any problem loading the exclusions, just continue without them\n                print(\"Warning: Could not load exclusions, continuing without them.\")\n                honor_exclusions = False\n\n        self.sites = {}\n\n        # Add all site information from the json file to internal site list.\n        for site_name in site_data:\n            try:\n\n                self.sites[site_name] = \\\n                    SiteInformation(site_name,\n                                    site_data[site_name][\"urlMain\"],\n                                    site_data[site_name][\"url\"],\n                                    site_data[site_name][\"username_claimed\"],\n                                    site_data[site_name],\n                                    site_data[site_name].get(\"isNSFW\",False)\n\n                                    )\n            except KeyError as error:\n                raise ValueError(\n                    f\"Problem parsing json contents at '{data_file_path}':  Missing attribute {error}.\"\n                )\n            except TypeError:\n                print(f\"Encountered TypeError parsing json contents for target '{site_name}' at {data_file_path}\\nSkipping target.\\n\")\n\n        return\n\n    def remove_nsfw_sites(self, do_not_remove: list = []):\n        \"\"\"\n        Remove NSFW sites from the sites, if isNSFW flag is true for site\n\n        Keyword Arguments:\n        self                   -- This object.\n\n        Return Value:\n        None\n        \"\"\"\n        sites = {}\n        do_not_remove = [site.casefold() for site in do_not_remove]\n        for site in self.sites:\n            if self.sites[site].is_nsfw and site.casefold() not in do_not_remove:\n                continue\n            sites[site] = self.sites[site]\n        self.sites =  sites\n\n    def site_name_list(self):\n        \"\"\"Get Site Name List.\n\n        Keyword Arguments:\n        self                   -- This object.\n\n        Return Value:\n        List of strings containing names of sites.\n        \"\"\"\n\n        return sorted([site.name for site in self], key=str.lower)\n\n    def __iter__(self):\n        \"\"\"Iterator For Object.\n\n        Keyword Arguments:\n        self                   -- This object.\n\n        Return Value:\n        Iterator for sites object.\n        \"\"\"\n\n        for site_name in self.sites:\n            yield self.sites[site_name]\n\n    def __len__(self):\n        \"\"\"Length For Object.\n\n        Keyword Arguments:\n        self                   -- This object.\n\n        Return Value:\n        Length of sites object.\n        \"\"\"\n        return len(self.sites)\n"
  },
  {
    "path": "tests/conftest.py",
    "content": "import os\nimport json\nimport urllib\nimport pytest\nfrom sherlock_project.sites import SitesInformation\n\ndef fetch_local_manifest(honor_exclusions: bool = True) -> dict[str, dict[str, str]]:\n    sites_obj = SitesInformation(data_file_path=os.path.join(os.path.dirname(__file__), \"../sherlock_project/resources/data.json\"), honor_exclusions=honor_exclusions)\n    sites_iterable: dict[str, dict[str, str]] = {site.name: site.information for site in sites_obj}\n    return sites_iterable\n\n@pytest.fixture()\ndef sites_obj():\n    sites_obj = SitesInformation(data_file_path=os.path.join(os.path.dirname(__file__), \"../sherlock_project/resources/data.json\"))\n    yield sites_obj\n\n@pytest.fixture(scope=\"session\")\ndef sites_info():\n    yield fetch_local_manifest()\n\n@pytest.fixture(scope=\"session\")\ndef remote_schema():\n    schema_url: str = 'https://raw.githubusercontent.com/sherlock-project/sherlock/master/sherlock_project/resources/data.schema.json'\n    with urllib.request.urlopen(schema_url) as remoteschema:\n        schemadat = json.load(remoteschema)\n    yield schemadat\n\ndef pytest_addoption(parser):\n    parser.addoption(\n        \"--chunked-sites\",\n        action=\"store\",\n        default=None,\n        help=\"For tests utilizing chunked sites, include only the (comma-separated) site(s) specified.\",\n    )\n\ndef pytest_generate_tests(metafunc):\n    if \"chunked_sites\" in metafunc.fixturenames:\n        sites_info = fetch_local_manifest(honor_exclusions=False)\n\n        # Ingest and apply site selections\n        site_filter: str | None = metafunc.config.getoption(\"--chunked-sites\")\n        if site_filter:\n            selected_sites: list[str] = [site.strip() for site in site_filter.split(\",\")]\n            sites_info = {\n                site: data for site, data in sites_info.items()\n                if site in selected_sites\n            }\n\n        params = [{name: data} for name, data in sites_info.items()]\n        ids = list(sites_info.keys())\n        metafunc.parametrize(\"chunked_sites\", params, ids=ids)\n"
  },
  {
    "path": "tests/few_test_basic.py",
    "content": "import sherlock_project\n\n#from sherlock.sites import SitesInformation\n#local_manifest = data_file_path=os.path.join(os.path.dirname(__file__), \"../sherlock/resources/data.json\")\n\ndef test_username_via_message():\n    sherlock_project.__main__(\"--version\")\n"
  },
  {
    "path": "tests/sherlock_interactives.py",
    "content": "import os\nimport platform\nimport re\nimport subprocess\n\nclass Interactives:\n    def run_cli(args:str = \"\") -> str:\n        \"\"\"Pass arguments to Sherlock as a normal user on the command line\"\"\"\n        # Adapt for platform differences (Windows likes to be special)\n        if platform.system() == \"Windows\":\n            command:str = f\"py -m sherlock_project {args}\"\n        else:\n            command:str = f\"sherlock {args}\"\n\n        proc_out:str = \"\"\n        try:\n            proc_out = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT)\n            return proc_out.decode()\n        except subprocess.CalledProcessError as e:\n            raise InteractivesSubprocessError(e.output.decode())\n\n\n    def walk_sherlock_for_files_with(pattern: str) -> list[str]:\n        \"\"\"Check all files within the Sherlock package for matching patterns\"\"\"\n        pattern:re.Pattern = re.compile(pattern)\n        matching_files:list[str] = []\n        for root, dirs, files in os.walk(\"sherlock_project\"):\n            for file in files:\n                file_path = os.path.join(root,file)\n                if \"__pycache__\" in file_path:\n                    continue\n                with open(file_path, 'r', errors='ignore') as f:\n                    if pattern.search(f.read()):\n                        matching_files.append(file_path)\n        return matching_files\n\nclass InteractivesSubprocessError(Exception):\n    pass\n"
  },
  {
    "path": "tests/test_manifest.py",
    "content": "import os\nimport json\nimport pytest\nfrom jsonschema import validate\n\ndef test_validate_manifest_against_local_schema():\n    \"\"\"Ensures that the manifest matches the local schema, for situations where the schema is being changed.\"\"\"\n    json_relative: str = '../sherlock_project/resources/data.json'\n    schema_relative: str = '../sherlock_project/resources/data.schema.json'\n\n    json_path: str = os.path.join(os.path.dirname(__file__), json_relative)\n    schema_path: str = os.path.join(os.path.dirname(__file__), schema_relative)\n\n    with open(json_path, 'r') as f:\n        jsondat = json.load(f)\n    with open(schema_path, 'r') as f:\n        schemadat = json.load(f)\n\n    validate(instance=jsondat, schema=schemadat)\n\n\n@pytest.mark.online\ndef test_validate_manifest_against_remote_schema(remote_schema):\n    \"\"\"Ensures that the manifest matches the remote schema, so as to not unexpectedly break clients.\"\"\"\n    json_relative: str = '../sherlock_project/resources/data.json'\n    json_path: str = os.path.join(os.path.dirname(__file__), json_relative)\n\n    with open(json_path, 'r') as f:\n        jsondat = json.load(f)\n\n    validate(instance=jsondat, schema=remote_schema)\n\n# Ensure that the expected values are beind returned by the site list\n@pytest.mark.parametrize(\"target_name,target_expected_err_type\", [\n    ('GitHub', 'status_code'),\n    ('GitLab', 'message'),\n])\ndef test_site_list_iterability (sites_info, target_name, target_expected_err_type):\n    assert sites_info[target_name]['errorType'] == target_expected_err_type\n"
  },
  {
    "path": "tests/test_probes.py",
    "content": "import pytest\nimport random\nimport string\nimport re\nfrom sherlock_project.sherlock import sherlock\nfrom sherlock_project.notify import QueryNotify\nfrom sherlock_project.result import QueryStatus\n#from sherlock_interactives import Interactives\n\n\ndef simple_query(sites_info: dict, site: str, username: str) -> QueryStatus:\n    query_notify = QueryNotify()\n    site_data: dict = {}\n    site_data[site] = sites_info[site]\n    return sherlock(\n        username=username,\n        site_data=site_data,\n        query_notify=query_notify,\n    )[site]['status'].status\n\n\n@pytest.mark.online\nclass TestLiveTargets:\n    \"\"\"Actively test probes against live and trusted targets\"\"\"\n    # Known positives should only use sites trusted to be reliable and unchanging\n    @pytest.mark.parametrize('site,username',[\n        ('GitLab', 'ppfeister'),\n        ('AllMyLinks', 'blue'),\n    ])\n    def test_known_positives_via_message(self, sites_info, site, username):\n        assert simple_query(sites_info=sites_info, site=site, username=username) is QueryStatus.CLAIMED\n\n\n    # Known positives should only use sites trusted to be reliable and unchanging\n    @pytest.mark.parametrize('site,username',[\n        ('GitHub', 'ppfeister'),\n        ('GitHub', 'sherlock-project'),\n        ('Docker Hub', 'ppfeister'),\n        ('Docker Hub', 'sherlock'),\n    ])\n    def test_known_positives_via_status_code(self, sites_info, site, username):\n        assert simple_query(sites_info=sites_info, site=site, username=username) is QueryStatus.CLAIMED\n\n\n    # Known positives should only use sites trusted to be reliable and unchanging\n    @pytest.mark.parametrize('site,username',[\n        ('Keybase', 'blue'),\n        ('devRant', 'blue'),\n    ])\n    def test_known_positives_via_response_url(self, sites_info, site, username):\n        assert simple_query(sites_info=sites_info, site=site, username=username) is QueryStatus.CLAIMED\n\n\n    # Randomly generate usernames of high length and test for positive availability\n    # Randomly generated usernames should be simple alnum for simplicity and high\n    # compatibility. Several attempts may be made ~just in case~ a real username is\n    # generated.\n    @pytest.mark.parametrize('site,random_len',[\n        ('GitLab', 255),\n        ('Codecademy', 30)\n    ])\n    def test_likely_negatives_via_message(self, sites_info, site, random_len):\n        num_attempts: int = 3\n        attempted_usernames: list[str] = []\n        status: QueryStatus = QueryStatus.CLAIMED\n        for i in range(num_attempts):\n            acceptable_types = string.ascii_letters + string.digits\n            random_handle = ''.join(random.choice(acceptable_types) for _ in range (random_len))\n            attempted_usernames.append(random_handle)\n            status = simple_query(sites_info=sites_info, site=site, username=random_handle)\n            if status is QueryStatus.AVAILABLE:\n                break\n        assert status is QueryStatus.AVAILABLE, f\"Could not validate available username after {num_attempts} attempts with randomly generated usernames {attempted_usernames}.\"\n\n\n    # Randomly generate usernames of high length and test for positive availability\n    # Randomly generated usernames should be simple alnum for simplicity and high\n    # compatibility. Several attempts may be made ~just in case~ a real username is\n    # generated.\n    @pytest.mark.parametrize('site,random_len',[\n        ('GitHub', 39),\n        ('Docker Hub', 30)\n    ])\n    def test_likely_negatives_via_status_code(self, sites_info, site, random_len):\n        num_attempts: int = 3\n        attempted_usernames: list[str] = []\n        status: QueryStatus = QueryStatus.CLAIMED\n        for i in range(num_attempts):\n            acceptable_types = string.ascii_letters + string.digits\n            random_handle = ''.join(random.choice(acceptable_types) for _ in range (random_len))\n            attempted_usernames.append(random_handle)\n            status = simple_query(sites_info=sites_info, site=site, username=random_handle)\n            if status is QueryStatus.AVAILABLE:\n                break\n        assert status is QueryStatus.AVAILABLE, f\"Could not validate available username after {num_attempts} attempts with randomly generated usernames {attempted_usernames}.\"\n\n\ndef test_username_illegal_regex(sites_info):\n    site: str = 'BitBucket'\n    invalid_handle: str = '*#$Y&*JRE'\n    pattern = re.compile(sites_info[site]['regexCheck'])\n    # Ensure that the username actually fails regex before testing sherlock\n    assert pattern.match(invalid_handle) is None\n    assert simple_query(sites_info=sites_info, site=site, username=invalid_handle) is QueryStatus.ILLEGAL\n\n"
  },
  {
    "path": "tests/test_ux.py",
    "content": "import pytest\nfrom sherlock_project import sherlock\nfrom sherlock_interactives import Interactives\nfrom sherlock_interactives import InteractivesSubprocessError\n\ndef test_remove_nsfw(sites_obj):\n    nsfw_target: str = 'Pornhub'\n    assert nsfw_target in {site.name: site.information for site in sites_obj}\n    sites_obj.remove_nsfw_sites()\n    assert nsfw_target not in {site.name: site.information for site in sites_obj}\n\n\n# Parametrized sites should *not* include Motherless, which is acting as the control\n@pytest.mark.parametrize('nsfwsites', [\n    ['Pornhub'],\n    ['Pornhub', 'Xvideos'],\n])\ndef test_nsfw_explicit_selection(sites_obj, nsfwsites):\n    for site in nsfwsites:\n        assert site in {site.name: site.information for site in sites_obj}\n    sites_obj.remove_nsfw_sites(do_not_remove=nsfwsites)\n    for site in nsfwsites:\n        assert site in {site.name: site.information for site in sites_obj}\n        assert 'Motherless' not in {site.name: site.information for site in sites_obj}\n\ndef test_wildcard_username_expansion():\n    assert sherlock.check_for_parameter('test{?}test') is True\n    assert sherlock.check_for_parameter('test{.}test') is False\n    assert sherlock.check_for_parameter('test{}test') is False\n    assert sherlock.check_for_parameter('testtest') is False\n    assert sherlock.check_for_parameter('test{?test') is False\n    assert sherlock.check_for_parameter('test?}test') is False\n    assert sherlock.multiple_usernames('test{?}test') == [\"test_test\" , \"test-test\" , \"test.test\"]\n\n\n@pytest.mark.parametrize('cliargs', [\n    '',\n    '--site urghrtuight --egiotr',\n    '--',\n])\ndef test_no_usernames_provided(cliargs):\n    with pytest.raises(InteractivesSubprocessError, match=r\"error: the following arguments are required: USERNAMES\"):\n        Interactives.run_cli(cliargs)\n"
  },
  {
    "path": "tests/test_validate_targets.py",
    "content": "import pytest\nimport re\nimport rstr\n\nfrom sherlock_project.sherlock import sherlock\nfrom sherlock_project.notify import QueryNotify\nfrom sherlock_project.result import QueryResult, QueryStatus\n\n\nFALSE_POSITIVE_ATTEMPTS: int = 2    # Since the usernames are randomly generated, it's POSSIBLE that a real username can be hit\nFALSE_POSITIVE_QUANTIFIER_UPPER_BOUND: int = 15  # If a pattern uses quantifiers such as `+` `*` or `{n,}`, limit the upper bound (0 to disable)\nFALSE_POSITIVE_DEFAULT_PATTERN: str = r'^[a-zA-Z0-9]{7,20}$'  # Used in absence of a regexCheck entry\n\n\ndef set_pattern_upper_bound(pattern: str, upper_bound: int = FALSE_POSITIVE_QUANTIFIER_UPPER_BOUND) -> str:\n    \"\"\"Set upper bound for regex patterns that use quantifiers such as `+` `*` or `{n,}`.\"\"\"\n    def replace_upper_bound(match: re.Match) -> str: # type: ignore\n        lower_bound: int = int(match.group(1)) if match.group(1) else 0 # type: ignore\n        nonlocal upper_bound\n        upper_bound = upper_bound if lower_bound < upper_bound else lower_bound # type: ignore  # noqa: F823\n        return f'{{{lower_bound},{upper_bound}}}'\n\n    pattern = re.sub(r'(?<!\\\\)\\{(\\d+),\\}', replace_upper_bound, pattern) # {n,} # type: ignore\n    pattern = re.sub(r'(?<!\\\\)\\+', f'{{1,{upper_bound}}}', pattern) # +\n    pattern = re.sub(r'(?<!\\\\)\\*', f'{{0,{upper_bound}}}', pattern) # *\n\n    return pattern\n\ndef false_positive_check(sites_info: dict[str, dict[str, str]], site: str, pattern: str) -> QueryStatus:\n    \"\"\"Check if a site is likely to produce false positives.\"\"\"\n    status: QueryStatus = QueryStatus.UNKNOWN\n\n    for _ in range(FALSE_POSITIVE_ATTEMPTS):\n        query_notify: QueryNotify = QueryNotify()\n        username: str = rstr.xeger(pattern)\n\n        result: QueryResult | str = sherlock(\n            username=username,\n            site_data=sites_info,\n            query_notify=query_notify,\n        )[site]['status']\n\n        if not hasattr(result, 'status'):\n            raise TypeError(f\"Result for site {site} does not have 'status' attribute. Actual result: {result}\")\n        if type(result.status) is not QueryStatus: # type: ignore\n            raise TypeError(f\"Result status for site {site} is not of type QueryStatus. Actual type: {type(result.status)}\") # type: ignore\n        status = result.status # type: ignore\n\n        if status in (QueryStatus.AVAILABLE, QueryStatus.WAF):\n            return status\n\n    return status\n\n\ndef false_negative_check(sites_info: dict[str, dict[str, str]], site: str) -> QueryStatus:\n    \"\"\"Check if a site is likely to produce false negatives.\"\"\"\n    status: QueryStatus = QueryStatus.UNKNOWN\n    query_notify: QueryNotify = QueryNotify()\n\n    result: QueryResult | str = sherlock(\n        username=sites_info[site]['username_claimed'],\n        site_data=sites_info,\n        query_notify=query_notify,\n    )[site]['status']\n\n    if not hasattr(result, 'status'):\n            raise TypeError(f\"Result for site {site} does not have 'status' attribute. Actual result: {result}\")\n    if type(result.status) is not QueryStatus: # type: ignore\n        raise TypeError(f\"Result status for site {site} is not of type QueryStatus. Actual type: {type(result.status)}\") # type: ignore\n    status = result.status # type: ignore\n\n    return status\n\n@pytest.mark.validate_targets\n@pytest.mark.online\nclass Test_All_Targets:\n\n    @pytest.mark.validate_targets_fp\n    def test_false_pos(self, chunked_sites: dict[str, dict[str, str]]):\n        \"\"\"Iterate through all sites in the manifest to discover possible false-positive inducting targets.\"\"\"\n        pattern: str\n        for site in chunked_sites:\n            try:\n                pattern = chunked_sites[site]['regexCheck']\n            except KeyError:\n                pattern = FALSE_POSITIVE_DEFAULT_PATTERN\n\n            if FALSE_POSITIVE_QUANTIFIER_UPPER_BOUND > 0:\n                pattern = set_pattern_upper_bound(pattern)\n\n            result: QueryStatus = false_positive_check(chunked_sites, site, pattern)\n            assert result is QueryStatus.AVAILABLE, f\"{site} produced false positive with pattern {pattern}, result was {result}\"\n\n    @pytest.mark.validate_targets_fn\n    def test_false_neg(self, chunked_sites: dict[str, dict[str, str]]):\n        \"\"\"Iterate through all sites in the manifest to discover possible false-negative inducting targets.\"\"\"\n        for site in chunked_sites:\n            result: QueryStatus = false_negative_check(chunked_sites, site)\n            assert result is QueryStatus.CLAIMED, f\"{site} produced false negative, result was {result}\"\n\n"
  },
  {
    "path": "tests/test_version.py",
    "content": "import os\nfrom sherlock_interactives import Interactives\nimport sherlock_project\n\ndef test_versioning() -> None:\n    # Ensure __version__ matches version presented to the user\n    assert sherlock_project.__version__ in Interactives.run_cli(\"--version\")\n    # Ensure __init__ is single source of truth for __version__ in package\n    # Temporarily allows sherlock.py so as to not trigger early upgrades\n    found:list = Interactives.walk_sherlock_for_files_with(r'__version__ *= *')\n    expected:list = [\n        # Normalization is REQUIRED for Windows ( / vs \\ )\n        os.path.normpath(\"sherlock_project/__init__.py\"),\n    ]\n    # Sorting is REQUIRED for Mac\n    assert sorted(found) == sorted(expected)\n"
  },
  {
    "path": "tox.ini",
    "content": "[tox]\nrequires =\n    tox >= 3\nenvlist =\n    lint\n    py313\n    py312\n    py311\n    py310\n\n[testenv]\ndescription = Attempt to build and install the package\ndeps =\n    coverage\n    jsonschema\n    pytest\n    rstr\nallowlist_externals = coverage\ncommands =\n    coverage run --source=sherlock_project --module pytest -v\n    coverage report --show-missing\n\n[testenv:offline]\ndeps =\n    jsonschema\n    pytest\ncommands =\n    pytest -v -m \"not online\"\n\n[testenv:lint]\ndescription = Lint with Ruff\ndeps =\n    ruff\ncommands =\n    ruff check\n\n[gh-actions]\npython =\n    3.13: py313\n    3.12: py312\n    3.11: py311\n    3.10: py310\n"
  }
]