# TikTok Boolean Search Scraper | Videos & Hashtags (`scraping_solutions/tiktok-boolean-search-scraper-videos-hashtags`) Actor

Find TikTok videos and photo posts with AND, OR, NOT, exact phrases, hashtags, date ranges, and engagement filters. Deduplicate results, discover creators and sounds, and export structured data without login or cookies.

- **URL**: https://apify.com/scraping\_solutions/tiktok-boolean-search-scraper-videos-hashtags.md
- **Developed by:** [Scraping Solutions](https://apify.com/scraping_solutions) (community)
- **Stats:** 6 total users, 4 monthly users, 92.9% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.90 / 1,000 matching tiktok results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## TikTok Boolean Search Scraper | Videos, Creators & Trends

Find public TikTok videos and photo posts with one precise Boolean query. Combine keywords, hashtags, exact phrases, `AND`, `OR`, `NOT`, parentheses, dates, content type, and engagement thresholds without manually merging separate searches.

The Actor turns each Boolean branch into a combined TikTok query, applies the **complete Boolean expression** to every candidate, removes duplicates, and streams matching records to the dataset as each page finishes. TikTok relevance discovers candidates but never replaces exact local validation.

### What you can use it for

- Social listening across brands, products, people, and topics
- Campaign and competitor monitoring
- Trend discovery with exclusions for noise, giveaways, or unrelated meanings
- Creator discovery based on actual content and engagement
- Research restricted to videos, photo posts, dates, views, likes, comments, shares, or saves
- Export-ready datasets for BI, research, alerts, and LLM workflows

### Boolean search examples

```text
(#skincare OR "skin routine") AND (serum OR sunscreen) AND NOT giveaway
```

```text
(BTC OR BITCOIN OR CRIPTO) AND TENDENCIA
```

```text
"Rafael Correa" AND CORRUPCION
```

Supported syntax:

| Syntax | Meaning | Example |
|---|---|---|
| `AND` | Every condition must match | `skincare AND serum` |
| `OR` | At least one condition must match | `BTC OR BITCOIN` |
| `NOT` | Exclude matching content | `running NOT giveaway` |
| `"phrase"` | Match an exact phrase | `"home workout"` |
| `( )` | Control grouping | `(nike OR adidas) AND running` |
| `#hashtag` | Search and match a hashtag | `#skincare` |

Before a paid run, check complex expressions with the free [FlujoDato Boolean Search Validator](https://flujodato.com/en/boolean-search-validator?platform=tiktok).

### How discovery works

1. The Actor validates and normalizes the Boolean expression.
2. Plain one-word terms use TikTok's video search, photo search, or both according to `contentType`, and also check the matching exact hashtag feed. Explicit hashtags are resolved once and then paginated through their public posts.
3. The coverage phase gives every generated search an initial opportunity.
4. The adaptive phase gives remaining pages to searches producing Boolean-qualified candidates, even when those candidates are rejected later by a date or engagement filter.
5. Every candidate is checked against the full Boolean expression and configured filters.
6. Unique matching results are saved immediately, so completed work remains available if a long run is stopped.

Plain terms and hashtags use Unicode-aware boundaries. A short term such as `IA` matches the complete word `IA`, but not text where those letters only occur inside `tía`, `viaje`, or `diario`.

Without date filters, `Efficient` coverage searches each Boolean branch as one combined query and may inspect up to 3 times the requested result count. `Comprehensive` keeps those combined queries and adds individual keyword, photo, and hashtag fallbacks, with up to 6 times the requested result count for higher recall. Every candidate from either coverage level must still satisfy the complete Boolean expression. When a date filter is active, successful pages become the cost guardrail and the candidate allowance expands to the estimated capacity of those pages.

For example, `google` checks keyword results, photo results, and the exact `#google` feed. Multi-word phrases are not silently converted into hashtags because `"digital marketing"` and `#digitalmarketing` are not equivalent searches.

### Pricing and coverage behavior

A very restrictive expression can return few or zero results. Positive terms from each Boolean branch are submitted together for discovery; the complete `AND`, `OR`, `NOT`, phrase, date, content-type, and engagement conditions are then validated after download. That means the Actor may inspect multiple pages before finding a match.

The pricing model has two events:

- **Matching TikTok result**: charged for each record successfully saved to the default dataset.
- **TikTok search page**: charged once for each successfully processed, non-empty provider page.

Failed requests, retry attempts, and empty pages do **not** trigger the search-page event. HTTP `429` and other temporary provider failures are retried after 4, 16, and 64 seconds; a larger valid `Retry-After` response is respected. If one discovery source still fails, its completed results remain available and the other sources continue. A non-empty page can still be charged when every candidate on it is rejected by the Boolean expression or local filters, because the upstream page was successfully retrieved and evaluated.

Before the first provider request, the Actor estimates its balanced maximum charge from the result target, discovery plan, and current Apify event prices. Date-filtered runs can use up to **0.5 successful pages per requested result in Efficient mode** and **1 page per requested result in Comprehensive mode**, shared across the complete plan. If the available charge is below the full estimate but can fund at least one successful page and one result, the Actor enters partial mode, streams affordable output, and stops safely at the charge limit.

### Input

```json
{
  "searchQuery": "(#skincare OR \"skin routine\") AND (serum OR sunscreen) AND NOT giveaway",
  "resultsLimit": 100,
  "contentType": "videos_only",
  "searchCoverage": "efficient",
  "oldestPostDate": "2026-08-01",
  "newestPostDate": "2026-09-03",
  "minimumViews": 1000,
  "minimumLikes": 50,
  "minimumComments": 0,
  "minimumShares": 0,
  "minimumSaves": 0,
  "strictBooleanSyntax": true
}
```

#### Input fields

| Field | Purpose |
|---|---|
| `searchQuery` | Required keyword, hashtag, phrase, or Boolean expression |
| `resultsLimit` | Maximum unique matches to save, from 1 to 10,000; it is not a guaranteed count |
| `contentType` | Search both videos and photos, videos only, or photo posts only |
| `searchCoverage` | `efficient` for lower exploration or `comprehensive` for higher recall |
| `oldestPostDate` / `newestPostDate` | Inclusive date range in `YYYY-MM-DD` |
| `minimumViews` | Minimum reported play count |
| `minimumLikes` | Minimum reported like count |
| `minimumComments` | Minimum reported comment count |
| `minimumShares` | Minimum reported share count |
| `minimumSaves` | Minimum reported save count |
| `strictBooleanSyntax` | Reject implicit operators instead of normalizing them |

### Output

Each result contains the query match context alongside normalized TikTok data:

```json
{
  "query": "#skincare AND serum",
  "normalizedQuery": "#skincare AND serum",
  "matchedTerms": ["#skincare", "serum"],
  "matchType": "exact_boolean",
  "discoveryType": "hashtag",
  "discoveryQuery": "skincare",
  "videoId": "7612345678901234567",
  "url": "https://www.tiktok.com/@skin.lab/video/7612345678901234567",
  "contentType": "video",
  "description": "Morning skin routine with serum #skincare",
  "hashtags": ["#skincare"],
  "publishedAt": "2026-08-01T12:30:00Z",
  "durationSeconds": 27,
  "viewCount": 120000,
  "likeCount": 8400,
  "commentCount": 320,
  "shareCount": 900,
  "saveCount": 1100,
  "creatorUsername": "skin.lab",
  "creatorName": "Skin Lab",
  "creatorVerified": false,
  "creatorFollowerCount": 42000,
  "musicId": "8765",
  "musicTitle": "Clean morning",
  "musicAuthor": "Example artist",
  "locationCreated": "US"
}
```

The default key-value store also exposes:

- `SEARCH_PLAN`: normalized query, diagnostics, generated searches, and budget estimate
- `RUN_PROGRESS`: live counters updated after completed pages
- `RUN_SUMMARY`: final scanned, matched, filtered, duplicate, request, and charge counts

### Recommended first run

Start with 25-100 results, `efficient` coverage, and moderate filters. Review `SEARCH_PLAN` before scaling. If too few records match, remove one restrictive `AND`/`NOT` condition or lower an engagement threshold before increasing the result target.

### Limitations

- Temporary provider failures use retries with 4, 16, and 64 second delays.
- Keyword, photo, and hashtag feeds are paginated while TikTok reports another page. Repeated cursors stop safely without charging or saving duplicate content.
- Explicit hashtags require a one-time lookup before their posts are loaded. This lookup is not billed as a search-page event.
- TikTok search endpoints return a ranked subset, not every post on the platform. A broad query can therefore finish below `resultsLimit` even when more matching posts exist on TikTok.
- Results are deduplicated globally by TikTok content ID.
- TikTok search is dynamic, so repeated runs may return different ordering or availability.
- Historical date filters cannot force TikTok search to jump directly to an old date.
- Public counts and metadata depend on what TikTok reports at collection time.

### Responsible use

Use the Actor only for lawful purposes. Collect public data that you are entitled to process, minimize personal data, respect intellectual-property and platform requirements, and comply with applicable privacy and data-protection laws. Do not use the Actor for harassment, unauthorized profiling, surveillance, or discriminatory decisions.

### Support

For reproducible problems, open an issue on the Actor page with the run ID, sanitized input, expected behavior, and observed behavior. Never include API keys, raw credentials, or private data. Provider-side availability can change; a run ID lets us distinguish a configuration problem from a temporary upstream issue.

### Developer setup

Add `RAPIDAPI_KEY` as a secret environment variable in the Actor. The key must be subscribed to the configured TikTok data API. Do not place credentials in source code, input, README examples, or datasets.

# Actor input Schema

## `searchQuery` (type: `string`):

Examples: #skincare; digital marketing; (#skincare OR "skin routine") AND serum AND NOT giveaway. Terms use whole-word boundaries, so IA does not match tía, viaje, or diario. More AND, NOT, phrase, date, or engagement restrictions can require additional paid search pages while producing fewer matches. [Validate the query before running](https://flujodato.com/en/boolean-search-validator?platform=tiktok).

## `resultsLimit` (type: `integer`):

Maximum number of unique TikTok posts saved after all filters, not a guaranteed count. TikTok search returns a ranked subset and can end before this limit. Successful non-empty search pages are charged separately, including pages whose candidates are all rejected.

## `contentType` (type: `string`):

Search both videos and photo posts, or limit discovery to one format. Explicit hashtag feeds can contain both formats and are filtered after discovery.

## `searchCoverage` (type: `string`):

Efficient uses one combined TikTok query per Boolean branch and normally scans up to 3x the requested result count. Comprehensive adds individual keyword, photo, and hashtag discovery fallbacks and normally scans up to 6x, while every saved result still requires exact Boolean validation. With date filters, the page allowance becomes the exploration guardrail. More scanned pages can increase cost.

## `oldestPostDate` (type: `string`):

Optional inclusive start date in YYYY-MM-DD format. TikTok search cannot jump directly to an old date, so narrow historical ranges may return fewer matches.

## `newestPostDate` (type: `string`):

Optional inclusive end date in YYYY-MM-DD format. Using the same date in both fields requests one calendar day.

## `minimumViews` (type: `integer`):

Save only posts with at least this many reported plays. Use 0 to disable the filter.

## `minimumLikes` (type: `integer`):

Save only posts with at least this many likes. Use 0 to disable the filter.

## `minimumComments` (type: `integer`):

Save only posts with at least this many comments. Use 0 to disable the filter.

## `minimumShares` (type: `integer`):

Save only posts with at least this many shares. Use 0 to disable the filter.

## `minimumSaves` (type: `integer`):

Save only posts with at least this many saves. Use 0 to disable the filter.

## `strictBooleanSyntax` (type: `boolean`):

Reject implicit expressions such as 'bank NOT jobs'. Leave disabled to normalize them to 'bank AND NOT jobs' with a warning.

## Actor input object example

```json
{
  "searchQuery": "(#skincare OR \"skin routine\") AND (serum OR sunscreen) AND NOT giveaway",
  "resultsLimit": 100,
  "contentType": "videos_and_photos",
  "searchCoverage": "efficient",
  "oldestPostDate": "",
  "newestPostDate": "",
  "minimumViews": 0,
  "minimumLikes": 0,
  "minimumComments": 0,
  "minimumShares": 0,
  "minimumSaves": 0,
  "strictBooleanSyntax": false
}
```

# Actor output Schema

## `results` (type: `string`):

All matching TikTok posts in the default dataset.

## `overview` (type: `string`):

Readable table with content, creator, engagement, music, and Boolean match information.

## `searchPlan` (type: `string`):

Normalized query, diagnostics, generated searches, and run-budget preflight.

## `runSummary` (type: `string`):

Final counts for scanned, matched, filtered, duplicate, charged, and requested records.

## `runProgress` (type: `string`):

Latest completed-page counters retained even when a long run is stopped.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("scraping_solutions/tiktok-boolean-search-scraper-videos-hashtags").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("scraping_solutions/tiktok-boolean-search-scraper-videos-hashtags").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call scraping_solutions/tiktok-boolean-search-scraper-videos-hashtags --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scraping_solutions/tiktok-boolean-search-scraper-videos-hashtags"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/QZtkj44IluoM3fxFG/builds/yLWB2gMiAajv2MRYf/openapi.json
