# Older Scrapy 2.x release notes

## Scrapy 2.13.4 (2025-11-17)

### Security bug fixes

- Improved protection against decompression bombs in
  [`HttpCompressionMiddleware`](../topics/downloader-middleware.md)
  for responses compressed using the `br` and `deflate` methods: if a
  single compressed chunk would be larger than the response size limit (see
  [`DOWNLOAD_MAXSIZE`](../topics/settings.md)) when decompressed, decompression is no longer
  carried out. This is especially important for the `br` (Brotli) method
  that can provide a very high compression ratio. Please, see the
  [CVE-2025-6176](https://nvd.nist.gov/vuln/detail/CVE-2025-6176) and [GHSA-2qfp-q593-8484](https://github.com/advisories/GHSA-2qfp-q593-8484) security advisories for more
  information.
  ([#7134](https://github.com/scrapy/scrapy/issues/7134))

### Modified requirements

- The minimum supported version of the optional `brotli` package is now
  `1.2.0`.
  ([#7134](https://github.com/scrapy/scrapy/issues/7134))
- The `brotlicffi` and `brotlipy` packages can no longer be used to
  decompress Brotli-compressed responses. Please install the `brotli`
  package instead.
  ([#7134](https://github.com/scrapy/scrapy/issues/7134))

### Other changes

- Restricted the maximum supported Twisted version to `25.5.0`, as Scrapy
  currently uses some private APIs changed in later Twisted versions.
  ([#7142](https://github.com/scrapy/scrapy/issues/7142))
- Stopped setting the `COVERAGE_CORE` environment variable in tests, it
  didn’t have an effect but caused the `coverage` module to produce a
  warning or an error.
  ([#7137](https://github.com/scrapy/scrapy/issues/7137))
- Removed the documentation build dependency on the deprecated
  `sphinx-hoverxref` module.
  ([#6786](https://github.com/scrapy/scrapy/issues/6786), [#6922](https://github.com/scrapy/scrapy/issues/6922))

## Scrapy 2.13.3 (2025-07-02)

- Changed the values for [`DOWNLOAD_DELAY`](../topics/settings.md) (from `0` to `1`) and
  [`CONCURRENT_REQUESTS_PER_DOMAIN`](../topics/settings.md) (from `8` to `1`) in the
  default project template.
  ([#6597](https://github.com/scrapy/scrapy/issues/6597), [#6918](https://github.com/scrapy/scrapy/issues/6918), [#6923](https://github.com/scrapy/scrapy/issues/6923))
- Improved [`scrapy.core.engine.ExecutionEngine`](../topics/api.md) logic related to
  initialization and exception handling, fixing several cases where the
  spider would crash, hang or log an unhandled exception.
  ([#6783](https://github.com/scrapy/scrapy/issues/6783), [#6784](https://github.com/scrapy/scrapy/issues/6784), [#6900](https://github.com/scrapy/scrapy/issues/6900), [#6908](https://github.com/scrapy/scrapy/issues/6908), [#6910](https://github.com/scrapy/scrapy/issues/6910),
  [#6911](https://github.com/scrapy/scrapy/issues/6911))
- Fixed a Windows issue with [feed exports](../topics/feed-exports.md) using
  [`scrapy.extensions.feedexport.FileFeedStorage`](../topics/feed-exports.md) that caused the file
  to be created on the wrong drive.
  ([#6894](https://github.com/scrapy/scrapy/issues/6894), [#6897](https://github.com/scrapy/scrapy/issues/6897))
- Allowed running tests with Twisted 25.5.0+ again. Pytest 8.4.1+ is now
  required for running tests in non-pinned envs as support for the new
  Twisted version was added in that version.
  ([#6893](https://github.com/scrapy/scrapy/issues/6893))
- Fixed running tests with lxml 6.0.0+.
  ([#6919](https://github.com/scrapy/scrapy/issues/6919))
- Added a deprecation notice for
  `scrapy.spidermiddlewares.offsite.OffsiteMiddleware` to the Scrapy
  2.11.2 release notes (see Scrapy 2.11.2 (2024-05-14)).
  ([#6926](https://github.com/scrapy/scrapy/issues/6926))
- Updated [contribution docs](../contributing.md) to refer to [ruff](https://docs.astral.sh/ruff/)
  instead of [black](https://black.readthedocs.io/en/stable/).
  ([#6903](https://github.com/scrapy/scrapy/issues/6903))
- Added `.venv/` and `.vscode/` to `.gitignore`.
  ([#6901](https://github.com/scrapy/scrapy/issues/6901), [#6907](https://github.com/scrapy/scrapy/issues/6907))

## Scrapy 2.13.2 (2025-06-09)

- Fixed a bug introduced in Scrapy 2.13.0 that caused results of request
  errbacks to be ignored when the errback was called because of a downloader
  error.
  ([#6861](https://github.com/scrapy/scrapy/issues/6861), [#6863](https://github.com/scrapy/scrapy/issues/6863))
- Added a note about the behavior change of
  `scrapy.utils.reactor.is_asyncio_reactor_installed` to its docs and
  to the “Backward-incompatible changes” section of the Scrapy 2.13.0
  release notes (see Scrapy 2.13.0 (2025-05-08)).
  ([#6866](https://github.com/scrapy/scrapy/issues/6866))
- Improved the message in the exception raised by
  `scrapy.utils.test.get_reactor_settings()` when there is no reactor
  installed.
  ([#6866](https://github.com/scrapy/scrapy/issues/6866))
- Updated the [`scrapy.crawler.CrawlerRunner`](../topics/api.md) examples in
  [Common Practices](../topics/practices.md) to install the reactor explicitly, to fix
  reactor-related errors with Scrapy 2.13.0 and later.
  ([#6865](https://github.com/scrapy/scrapy/issues/6865))
- Fixed `scrapy fetch` not working with [scrapy-poet](https://github.com/scrapinghub/scrapy-poet).
  ([#6872](https://github.com/scrapy/scrapy/issues/6872))
- Fixed an exception produced by [`scrapy.core.engine.ExecutionEngine`](../topics/api.md)
  when it’s closed before being fully initialized.
  ([#6857](https://github.com/scrapy/scrapy/issues/6857), [#6867](https://github.com/scrapy/scrapy/issues/6867))
- Improved the README and updated the Scrapy logo in it.
  ([#6831](https://github.com/scrapy/scrapy/issues/6831), [#6833](https://github.com/scrapy/scrapy/issues/6833), [#6839](https://github.com/scrapy/scrapy/issues/6839))
- Restricted the Twisted version used in tests to below 25.5.0, as some tests
  fail with 25.5.0.
  ([#6878](https://github.com/scrapy/scrapy/issues/6878), [#6882](https://github.com/scrapy/scrapy/issues/6882))
- Updated type hints for Twisted 25.5.0 changes.
  ([#6882](https://github.com/scrapy/scrapy/issues/6882))
- Removed the old artwork.
  ([#6874](https://github.com/scrapy/scrapy/issues/6874))

## Scrapy 2.13.1 (2025-05-28)

- Gave callback requests precedence over start requests when priority values
  are the same.

  This makes the changes from 2.13.0 to start request handling more intuitive
  and backward compatible. For scenarios where all requests have the same
  priorities, in 2.13.0 all start requests were sent before the first
  callback request. In 2.13.1, the same as in 2.12 and lower, start requests
  are only sent when there are not enough pending callback requests to reach
  concurrency limits.

  ([#6828](https://github.com/scrapy/scrapy/issues/6828))
- Added a [deepwiki](https://deepwiki.com/scrapy/scrapy) badge to the README. ([#6793](https://github.com/scrapy/scrapy/issues/6793))
- Fixed a typo in the code example of [Delaying start request iteration](../topics/spiders.md).
  ([#6812](https://github.com/scrapy/scrapy/issues/6812), [#6815](https://github.com/scrapy/scrapy/issues/6815))
- Fixed a typo in the [Supported callables](../topics/coroutines.md) section of the documentation.
  ([#6822](https://github.com/scrapy/scrapy/issues/6822))
- Made this page more prominently listed in PyPI project links.
  ([#6826](https://github.com/scrapy/scrapy/issues/6826))

## Scrapy 2.13.0 (2025-05-08)

Highlights:

- The asyncio reactor is now enabled by default
- Replaced `start_requests()` (sync) with [`start()`](../topics/spiders.md)
  (async) and changed how it is iterated
- Added the [`allow_offsite`](../topics/downloader-middleware.md) request meta key
- Spider middlewares that don’t support asynchronous spider output are
  deprecated
- Added a base class for [universal spider middlewares](../topics/spider-middleware.md)

### Modified requirements

- Dropped support for PyPy 3.9.
  ([#6613](https://github.com/scrapy/scrapy/issues/6613))
- Added support for PyPy 3.11.
  ([#6697](https://github.com/scrapy/scrapy/issues/6697))

### Backward-incompatible changes

- The default value of the `TWISTED_REACTOR` setting was changed
  from `None` to
  `"twisted.internet.asyncioreactor.AsyncioSelectorReactor"`. This value
  was used in newly generated projects since Scrapy 2.7.0 but now existing
  projects that don’t explicitly set this setting will also use the asyncio
  reactor. You can change this setting in your project to use a different
  reactor.
  ([#6659](https://github.com/scrapy/scrapy/issues/6659), [#6713](https://github.com/scrapy/scrapy/issues/6713))
- The iteration of start requests and items no longer stops once there are
  requests in the scheduler, and instead runs continuously until all start
  requests have been scheduled.

  To reproduce the previous behavior, see [Delaying start request iteration](../topics/spiders.md).
  ([#6729](https://github.com/scrapy/scrapy/issues/6729))
- An unhandled exception from the
  `open_spider()` method of a
  [spider middleware](../topics/spider-middleware.md) no longer stops the
  crawl.
  ([#6729](https://github.com/scrapy/scrapy/issues/6729))
- In `scrapy.core.engine.ExecutionEngine`:
  - The second parameter of `open_spider()`, `start_requests`, has been
    removed. The start requests are determined by the `spider` parameter
    instead (see [`start()`](../topics/spiders.md)).
  - The `slot` attribute has been renamed to `_slot` and should not be
    used.

  ([#6729](https://github.com/scrapy/scrapy/issues/6729))
- In `scrapy.core.engine`, the `Slot` class has been renamed to `_Slot`
  and should not be used.
  ([#6729](https://github.com/scrapy/scrapy/issues/6729))
- The `slot` [telnet variable](../topics/telnetconsole.md "Available variables in the telnet console") has been removed.
  ([#6729](https://github.com/scrapy/scrapy/issues/6729))
- In `scrapy.core.spidermw.SpiderMiddlewareManager`,
  `process_start_requests()` has been replaced by `process_start()`.
  ([#6729](https://github.com/scrapy/scrapy/issues/6729))
- The `scrape_func` callable passed to
  `scrapy.core.spidermw.SpiderMiddlewareManager.scrape_response()` is now
  called with 2 parameters, `response` and `request`, instead of 3, and
  must return a [`Deferred`](https://docs.twisted.org/en/stable/api/twisted.internet.defer.Deferred.html) instead of an
  iterable.
  ([#6787](https://github.com/scrapy/scrapy/issues/6787))
- The now-deprecated `start_requests()` method, when it returns an iterable
  instead of being defined as a generator, is now executed *after* the
  [scheduler](../topics/scheduler.md) instance has been created.
  ([#6729](https://github.com/scrapy/scrapy/issues/6729))
- When using [`JOBDIR`](../topics/settings.md), [start requests](../topics/spiders.md) are
  now serialized into their own, `s`-suffixed priority folders. You can set
  [`SCHEDULER_START_DISK_QUEUE`](../topics/settings.md) to `None` or `""` to change that,
  but the side effects may be undesirable. See
  [`SCHEDULER_START_DISK_QUEUE`](../topics/settings.md) for details.
  ([#6729](https://github.com/scrapy/scrapy/issues/6729))
- The URL length limit, set by the [`URLLENGTH_LIMIT`](../topics/settings.md) setting, is now
  also enforced for start requests.
  ([#6777](https://github.com/scrapy/scrapy/issues/6777))
- Calling `scrapy.utils.reactor.is_asyncio_reactor_installed` without
  an installed reactor now raises an exception instead of installing a
  reactor. This shouldn’t affect normal Scrapy use cases, but it may affect
  3rd-party test suites that use Scrapy internals such as
  [`Crawler`](../topics/api.md) and don’t install a reactor explicitly. If
  you are affected by this change, you most likely need to install the
  reactor before running Scrapy code that expects it to be installed.
  ([#6732](https://github.com/scrapy/scrapy/issues/6732), [#6735](https://github.com/scrapy/scrapy/issues/6735))
- The `from_settings()` method of
  [`UrlLengthMiddleware`](../topics/spider-middleware.md),
  deprecated in Scrapy 2.12.0, is removed earlier than the usual deprecation
  period (this was needed because after the introduction of the
  [`BaseSpiderMiddleware`](../topics/spider-middleware.md) base class and
  switching built-in spider middlewares to it those middlewares need the
  [`Crawler`](../topics/api.md) instance at run time). Please use
  `from_crawler()` instead.
  ([#6693](https://github.com/scrapy/scrapy/issues/6693))
- `scrapy.utils.url.escape_ajax()` is no longer called when a
  [`Request`](../topics/request-response.md) instance is created. It was only useful for
  websites supporting the `_escaped_fragment_` feature which most modern
  websites don’t support. If you still need this you can modify the URLs
  before passing them to [`Request`](../topics/request-response.md).
  ([#6523](https://github.com/scrapy/scrapy/issues/6523), [#6651](https://github.com/scrapy/scrapy/issues/6651))

### Deprecation removals

- Removed old deprecated name aliases for some signals:
  - `stats_spider_opened` (use `spider_opened` instead)
  - `stats_spider_closing` and `stats_spider_closed` (use
    `spider_closed` instead)
  - `item_passed` (use `item_scraped` instead)
  - `request_received` (use `request_scheduled` instead)

  ([#6654](https://github.com/scrapy/scrapy/issues/6654), [#6655](https://github.com/scrapy/scrapy/issues/6655))

### Deprecations

- The `start_requests()` method of [`Spider`](../topics/spiders.md) is deprecated,
  use [`start()`](../topics/spiders.md) instead, or both to maintain support for
  lower Scrapy versions.
  ([#456](https://github.com/scrapy/scrapy/issues/456), [#3477](https://github.com/scrapy/scrapy/issues/3477), [#4467](https://github.com/scrapy/scrapy/issues/4467), [#5627](https://github.com/scrapy/scrapy/issues/5627), [#6729](https://github.com/scrapy/scrapy/issues/6729))
- The `process_start_requests()` method of [spider middlewares](../topics/spider-middleware.md) is deprecated, use
  [`process_start()`](../topics/spider-middleware.md) instead,
  or both to maintain support for lower Scrapy versions.
  ([#456](https://github.com/scrapy/scrapy/issues/456), [#3477](https://github.com/scrapy/scrapy/issues/3477), [#4467](https://github.com/scrapy/scrapy/issues/4467), [#5627](https://github.com/scrapy/scrapy/issues/5627), [#6729](https://github.com/scrapy/scrapy/issues/6729))
- The `__init__` method of priority queue classes (see
  [`SCHEDULER_PRIORITY_QUEUE`](../topics/settings.md)) should now support a keyword-only
  `start_queue_cls` parameter.
  ([#6752](https://github.com/scrapy/scrapy/issues/6752))
- Spider middlewares that don’t support asynchronous spider output are
  deprecated. The async iterable downgrading feature, needed for using such
  middlewares with asynchronous callbacks and with other spider middlewares
  that produce asynchronous iterables, is also deprecated. Please update all
  such middlewares to support asynchronous spider output. ([#6664](https://github.com/scrapy/scrapy/issues/6664))
- Functions that were imported from [`w3lib.url`](https://w3lib.readthedocs.io/en/latest/w3lib.html#module-w3lib.url) and re-exported in
  `scrapy.utils.url` are now deprecated, you should import them from
  [`w3lib.url`](https://w3lib.readthedocs.io/en/latest/w3lib.html#module-w3lib.url) directly. They are:
  - `scrapy.utils.url.add_or_replace_parameter()`
  - `scrapy.utils.url.add_or_replace_parameters()`
  - `scrapy.utils.url.any_to_uri()`
  - `scrapy.utils.url.canonicalize_url()`
  - `scrapy.utils.url.file_uri_to_path()`
  - `scrapy.utils.url.is_url()`
  - `scrapy.utils.url.parse_data_uri()`
  - `scrapy.utils.url.parse_url()`
  - `scrapy.utils.url.path_to_file_uri()`
  - `scrapy.utils.url.safe_download_url()`
  - `scrapy.utils.url.safe_url_string()`
  - `scrapy.utils.url.url_query_cleaner()`
  - `scrapy.utils.url.url_query_parameter()`

  ([#4577](https://github.com/scrapy/scrapy/issues/4577), [#6583](https://github.com/scrapy/scrapy/issues/6583), [#6586](https://github.com/scrapy/scrapy/issues/6586))
- HTTP/1.0 support code is deprecated. It was disabled by default and
  couldn’t be used together with HTTP/1.1. If you still need it, you should
  write your own download handler or copy the code from Scrapy. The
  deprecations include:
  - `scrapy.core.downloader.handlers.http10.HTTP10DownloadHandler`
  - `scrapy.core.downloader.webclient.ScrapyHTTPClientFactory`
  - `scrapy.core.downloader.webclient.ScrapyHTTPPageGetter`
  - Overriding
    `scrapy.core.downloader.contextfactory.ScrapyClientContextFactory.getContext()`

  ([#6634](https://github.com/scrapy/scrapy/issues/6634))
- The following modules and functions used only in tests are deprecated:
  - the `scrapy.utils.testproc` module
  - the `scrapy.utils.testsite` module
  - `scrapy.utils.test.assert_gcs_environ()`
  - `scrapy.utils.test.get_ftp_content_and_delete()`
  - `scrapy.utils.test.get_gcs_content_and_delete()`
  - `scrapy.utils.test.mock_google_cloud_storage()`
  - `scrapy.utils.test.skip_if_no_boto()`

  If you need to use them in your tests or code, you can copy the code from Scrapy.
  ([#6696](https://github.com/scrapy/scrapy/issues/6696))
- `scrapy.utils.test.TestSpider` is deprecated. If you need an empty spider
  class you can use `scrapy.utils.spider.DefaultSpider` or create your
  own subclass of [`scrapy.Spider`](../topics/spiders.md).
  ([#6678](https://github.com/scrapy/scrapy/issues/6678))
- `scrapy.downloadermiddlewares.ajaxcrawl.AjaxCrawlMiddleware` is
  deprecated. It was disabled by default and isn’t useful for most of the
  existing websites.
  ([#6523](https://github.com/scrapy/scrapy/issues/6523), [#6651](https://github.com/scrapy/scrapy/issues/6651), [#6656](https://github.com/scrapy/scrapy/issues/6656))
- `scrapy.utils.url.escape_ajax()` is deprecated.
  ([#6523](https://github.com/scrapy/scrapy/issues/6523), [#6651](https://github.com/scrapy/scrapy/issues/6651))
- `scrapy.spiders.init.InitSpider` is deprecated. If you find it useful,
  you can copy its code from Scrapy.
  ([#6708](https://github.com/scrapy/scrapy/issues/6708), [#6714](https://github.com/scrapy/scrapy/issues/6714))
- `scrapy.utils.versions.scrapy_components_versions()` is deprecated, use
  `scrapy.utils.versions.get_versions()` instead.
  ([#6582](https://github.com/scrapy/scrapy/issues/6582))
- `BaseDupeFilter.log()` is deprecated. It does nothing and shouldn’t be
  called.
  ([#4151](https://github.com/scrapy/scrapy/issues/4151))
- Passing the `spider` argument to the following methods of
  `Scraper` is deprecated:
  - `close_spider()`
  - `enqueue_scrape()`
  - `handle_spider_error()`
  - `handle_spider_output()`

  ([#6764](https://github.com/scrapy/scrapy/issues/6764))

### New features

- You can now yield the start requests and items of a spider from the
  [`start()`](../topics/spiders.md) spider method and from the
  [`process_start()`](../topics/spider-middleware.md) spider
  middleware method, both [asynchronous generators](https://docs.python.org/3/glossary.html#term-asynchronous-generator).

  This makes it possible to use asynchronous code to generate those start
  requests and items, e.g. reading them from a queue service or database
  using an asynchronous client, without workarounds.
  ([#456](https://github.com/scrapy/scrapy/issues/456), [#3477](https://github.com/scrapy/scrapy/issues/3477), [#4467](https://github.com/scrapy/scrapy/issues/4467), [#5627](https://github.com/scrapy/scrapy/issues/5627), [#6729](https://github.com/scrapy/scrapy/issues/6729))
- Start requests are now [scheduled](../topics/scheduler.md) as soon as
  possible.

  As a result, their [`priority`](../topics/request-response.md) is now taken into
  account as soon as [`CONCURRENT_REQUESTS`](../topics/settings.md) is reached.
  ([#456](https://github.com/scrapy/scrapy/issues/456), [#3477](https://github.com/scrapy/scrapy/issues/3477), [#4467](https://github.com/scrapy/scrapy/issues/4467), [#5627](https://github.com/scrapy/scrapy/issues/5627), [#6729](https://github.com/scrapy/scrapy/issues/6729))
- [`Crawler.signals`](../topics/api.md) has a new
  [`wait_for()`](../topics/api.md) method.
  ([#6729](https://github.com/scrapy/scrapy/issues/6729))
- Added a new [`scheduler_empty`](../topics/signals.md) signal.
  ([#6729](https://github.com/scrapy/scrapy/issues/6729))
- Added new settings: [`SCHEDULER_START_DISK_QUEUE`](../topics/settings.md) and
  [`SCHEDULER_START_MEMORY_QUEUE`](../topics/settings.md).
  ([#6729](https://github.com/scrapy/scrapy/issues/6729))
- Added [`StartSpiderMiddleware`](../topics/spider-middleware.md), which
  sets [`is_start_request`](../topics/spider-middleware.md) to `True` on [start requests](../topics/spiders.md).
  ([#6729](https://github.com/scrapy/scrapy/issues/6729))
- Exposed a new method of [`Crawler.engine`](../topics/api.md):
  [`needs_backout()`](../topics/api.md).
  ([#6729](https://github.com/scrapy/scrapy/issues/6729))
- Added the [`allow_offsite`](../topics/downloader-middleware.md) request meta key that can be used
  instead of the more general [`dont_filter`](../topics/request-response.md) request
  attribute to skip processing of the request by
  [`OffsiteMiddleware`](../topics/downloader-middleware.md) (but not
  by other code that checks [`dont_filter`](../topics/request-response.md)).
  ([#3690](https://github.com/scrapy/scrapy/issues/3690), [#6151](https://github.com/scrapy/scrapy/issues/6151), [#6366](https://github.com/scrapy/scrapy/issues/6366))
- Added an optional base class for spider middlewares,
  [`BaseSpiderMiddleware`](../topics/spider-middleware.md), which can be
  helpful for writing [universal spider middlewares](../topics/spider-middleware.md) without boilerplate and code duplication.
  The built-in spider middlewares now inherit from this class.
  ([#6693](https://github.com/scrapy/scrapy/issues/6693), [#6777](https://github.com/scrapy/scrapy/issues/6777))
- [Scrapy add-ons](../topics/addons.md) can now define a class method called
  `update_pre_crawler_settings()` to update [pre-crawler settings](../topics/settings.md).
  ([#6544](https://github.com/scrapy/scrapy/issues/6544), [#6568](https://github.com/scrapy/scrapy/issues/6568))
- Added [helpers](../topics/addons.md) for modifying [component
  priority dictionary](../topics/settings.md "Component priority dictionaries") settings.
  ([#6614](https://github.com/scrapy/scrapy/issues/6614))
- Responses that use an unknown/unsupported encoding now produce a warning.
  If Scrapy knows that installing an additional package (such as [brotli](https://github.com/google/brotli))
  will allow decoding the response, that will be mentioned in the warning.
  ([#4697](https://github.com/scrapy/scrapy/issues/4697), [#6618](https://github.com/scrapy/scrapy/issues/6618))
- Added the `spider_exceptions/count` stat which tracks the total count of
  exceptions (tracked also by per-type `spider_exceptions/*` stats).
  ([#6739](https://github.com/scrapy/scrapy/issues/6739), [#6740](https://github.com/scrapy/scrapy/issues/6740))
- Added the [`DEFAULT_DROPITEM_LOG_LEVEL`](../topics/settings.md) setting and the
  `scrapy.exceptions.DropItem.log_level` attribute that allow
  customizing the log level of the message that is logged when an item is
  dropped.
  ([#6603](https://github.com/scrapy/scrapy/issues/6603), [#6608](https://github.com/scrapy/scrapy/issues/6608))
- Added support for the `-b, --cookie` curl argument to
  [`scrapy.Request.from_curl()`](../topics/request-response.md).
  ([#6684](https://github.com/scrapy/scrapy/issues/6684))
- Added the [`LOG_VERSIONS`](../topics/settings.md) setting that allows customizing the
  list of software whose versions are logged when the spider starts.
  ([#6582](https://github.com/scrapy/scrapy/issues/6582))
- Added the [`WARN_ON_GENERATOR_RETURN_VALUE`](../topics/settings.md) setting that allows
  disabling run time analysis of callback code used to warn about incorrect
  `return` statements in generator-based callbacks. You may need to disable
  this setting if this analysis breaks on your callback code.
  ([#6731](https://github.com/scrapy/scrapy/issues/6731), [#6738](https://github.com/scrapy/scrapy/issues/6738))

### Improvements

- Removed or postponed some calls of `itemadapter.is_item()` to increase
  performance.
  ([#6719](https://github.com/scrapy/scrapy/issues/6719))
- Improved the error message when running a `scrapy` command that requires
  a project (such as `scrapy crawl`) outside of a project directory.
  ([#2349](https://github.com/scrapy/scrapy/issues/2349), [#3426](https://github.com/scrapy/scrapy/issues/3426))
- Added an empty [`ADDONS`](../topics/settings.md) setting to the `settings.py` template
  for new projects.
  ([#6587](https://github.com/scrapy/scrapy/issues/6587))

### Bug fixes

- Yielding an item from [`Spider.start`](../topics/spiders.md) or from
  [`SpiderMiddleware.process_start`](../topics/spider-middleware.md) no longer delays
  the next iteration of starting requests and items by up to 5 seconds.
  ([#6729](https://github.com/scrapy/scrapy/issues/6729))
- Fixed calculation of `items_per_minute` and `responses_per_minute`
  stats.
  ([#6599](https://github.com/scrapy/scrapy/issues/6599))
- Fixed an error initializing
  [`scrapy.extensions.feedexport.GCSFeedStorage`](../topics/feed-exports.md).
  ([#6617](https://github.com/scrapy/scrapy/issues/6617), [#6628](https://github.com/scrapy/scrapy/issues/6628))
- Fixed an error running `scrapy bench`.
  ([#6632](https://github.com/scrapy/scrapy/issues/6632), [#6633](https://github.com/scrapy/scrapy/issues/6633))
- Fixed duplicated log messages about the reactor and the event loop.
  ([#6636](https://github.com/scrapy/scrapy/issues/6636), [#6657](https://github.com/scrapy/scrapy/issues/6657))
- Fixed resolving type annotations of `SitemapSpider._parse_sitemap()` at
  run time, required by tools such as [scrapy-poet](https://github.com/scrapinghub/scrapy-poet).
  ([#6665](https://github.com/scrapy/scrapy/issues/6665), [#6671](https://github.com/scrapy/scrapy/issues/6671))
- Calling `scrapy.utils.reactor.is_asyncio_reactor_installed` without
  an installed reactor now raises an exception instead of installing a
  reactor.
  ([#6732](https://github.com/scrapy/scrapy/issues/6732), [#6735](https://github.com/scrapy/scrapy/issues/6735))
- Restored support for the `x-gzip` content encoding.
  ([#6618](https://github.com/scrapy/scrapy/issues/6618))

### Documentation

- Documented the setting values set in the default project template.
  ([#6762](https://github.com/scrapy/scrapy/issues/6762), [#6775](https://github.com/scrapy/scrapy/issues/6775))
- Improved the docs about asynchronous iterable support in spider
  middlewares. ([#6688](https://github.com/scrapy/scrapy/issues/6688))
- Improved the [docs](../topics/coroutines.md "Using Deferred-based APIs") about using
  [`Deferred`](https://docs.twisted.org/en/stable/api/twisted.internet.defer.Deferred.html)-based APIs in coroutine-based
  code and included a list of such APIs.
  ([#6677](https://github.com/scrapy/scrapy/issues/6677), [#6734](https://github.com/scrapy/scrapy/issues/6734), [#6776](https://github.com/scrapy/scrapy/issues/6776))
- Improved the [contribution docs](../contributing.md).
  ([#6561](https://github.com/scrapy/scrapy/issues/6561), [#6575](https://github.com/scrapy/scrapy/issues/6575))
- Removed the `Splash` recommendation from the [headless browser](../topics/dynamic-content.md "Using a headless browser") suggestion. We no longer recommend using
  `Splash` and recommend using other headless browser solutions instead.
  ([#6642](https://github.com/scrapy/scrapy/issues/6642), [#6701](https://github.com/scrapy/scrapy/issues/6701))
- Added the dark mode to the HTML documentation.
  ([#6653](https://github.com/scrapy/scrapy/issues/6653))
- Other documentation improvements and fixes.
  ([#4151](https://github.com/scrapy/scrapy/issues/4151),
  [#6526](https://github.com/scrapy/scrapy/issues/6526),
  [#6620](https://github.com/scrapy/scrapy/issues/6620),
  [#6621](https://github.com/scrapy/scrapy/issues/6621),
  [#6622](https://github.com/scrapy/scrapy/issues/6622),
  [#6623](https://github.com/scrapy/scrapy/issues/6623),
  [#6624](https://github.com/scrapy/scrapy/issues/6624),
  [#6721](https://github.com/scrapy/scrapy/issues/6721),
  [#6723](https://github.com/scrapy/scrapy/issues/6723),
  [#6780](https://github.com/scrapy/scrapy/issues/6780))

### Packaging

- Switched from `setup.py` to `pyproject.toml`.
  ([#6514](https://github.com/scrapy/scrapy/issues/6514), [#6547](https://github.com/scrapy/scrapy/issues/6547))
- Switched the build backend from [setuptools](https://pypi.org/project/setuptools/) to [hatchling](https://pypi.org/project/hatchling/).
  ([#6771](https://github.com/scrapy/scrapy/issues/6771))

### Quality assurance

- Replaced most linters with [ruff](https://docs.astral.sh/ruff/).
  ([#6565](https://github.com/scrapy/scrapy/issues/6565),
  [#6576](https://github.com/scrapy/scrapy/issues/6576),
  [#6577](https://github.com/scrapy/scrapy/issues/6577),
  [#6581](https://github.com/scrapy/scrapy/issues/6581),
  [#6584](https://github.com/scrapy/scrapy/issues/6584),
  [#6595](https://github.com/scrapy/scrapy/issues/6595),
  [#6601](https://github.com/scrapy/scrapy/issues/6601),
  [#6631](https://github.com/scrapy/scrapy/issues/6631))
- Improved accuracy and performance of collecting test coverage.
  ([#6255](https://github.com/scrapy/scrapy/issues/6255), [#6610](https://github.com/scrapy/scrapy/issues/6610))
- Fixed an error that prevented running tests from directories other than the
  top level source directory.
  ([#6567](https://github.com/scrapy/scrapy/issues/6567))
- Reduced the amount of `mockserver` calls in tests to improve the overall
  test run time.
  ([#6637](https://github.com/scrapy/scrapy/issues/6637), [#6648](https://github.com/scrapy/scrapy/issues/6648))
- Fixed tests that were running the same test code more than once.
  ([#6646](https://github.com/scrapy/scrapy/issues/6646), [#6647](https://github.com/scrapy/scrapy/issues/6647), [#6650](https://github.com/scrapy/scrapy/issues/6650))
- Refactored tests to use more `pytest` features instead of `unittest`
  ones where possible.
  ([#6678](https://github.com/scrapy/scrapy/issues/6678),
  [#6680](https://github.com/scrapy/scrapy/issues/6680),
  [#6695](https://github.com/scrapy/scrapy/issues/6695),
  [#6699](https://github.com/scrapy/scrapy/issues/6699),
  [#6700](https://github.com/scrapy/scrapy/issues/6700),
  [#6702](https://github.com/scrapy/scrapy/issues/6702),
  [#6709](https://github.com/scrapy/scrapy/issues/6709),
  [#6710](https://github.com/scrapy/scrapy/issues/6710),
  [#6711](https://github.com/scrapy/scrapy/issues/6711),
  [#6712](https://github.com/scrapy/scrapy/issues/6712),
  [#6725](https://github.com/scrapy/scrapy/issues/6725))
- Type hints improvements and fixes.
  ([#6578](https://github.com/scrapy/scrapy/issues/6578),
  [#6579](https://github.com/scrapy/scrapy/issues/6579),
  [#6593](https://github.com/scrapy/scrapy/issues/6593),
  [#6605](https://github.com/scrapy/scrapy/issues/6605),
  [#6694](https://github.com/scrapy/scrapy/issues/6694))
- CI and test improvements and fixes.
  ([#5360](https://github.com/scrapy/scrapy/issues/5360),
  [#6271](https://github.com/scrapy/scrapy/issues/6271),
  [#6547](https://github.com/scrapy/scrapy/issues/6547),
  [#6560](https://github.com/scrapy/scrapy/issues/6560),
  [#6602](https://github.com/scrapy/scrapy/issues/6602),
  [#6607](https://github.com/scrapy/scrapy/issues/6607),
  [#6609](https://github.com/scrapy/scrapy/issues/6609),
  [#6613](https://github.com/scrapy/scrapy/issues/6613),
  [#6619](https://github.com/scrapy/scrapy/issues/6619),
  [#6626](https://github.com/scrapy/scrapy/issues/6626),
  [#6679](https://github.com/scrapy/scrapy/issues/6679),
  [#6703](https://github.com/scrapy/scrapy/issues/6703),
  [#6704](https://github.com/scrapy/scrapy/issues/6704),
  [#6716](https://github.com/scrapy/scrapy/issues/6716),
  [#6720](https://github.com/scrapy/scrapy/issues/6720),
  [#6722](https://github.com/scrapy/scrapy/issues/6722),
  [#6724](https://github.com/scrapy/scrapy/issues/6724),
  [#6741](https://github.com/scrapy/scrapy/issues/6741),
  [#6743](https://github.com/scrapy/scrapy/issues/6743),
  [#6766](https://github.com/scrapy/scrapy/issues/6766),
  [#6770](https://github.com/scrapy/scrapy/issues/6770),
  [#6772](https://github.com/scrapy/scrapy/issues/6772),
  [#6773](https://github.com/scrapy/scrapy/issues/6773))
- Code cleanups.
  ([#6600](https://github.com/scrapy/scrapy/issues/6600),
  [#6606](https://github.com/scrapy/scrapy/issues/6606),
  [#6635](https://github.com/scrapy/scrapy/issues/6635),
  [#6764](https://github.com/scrapy/scrapy/issues/6764))

## Scrapy 2.12.0 (2024-11-18)

Highlights:

- Dropped support for Python 3.8, added support for Python 3.13
- `scrapy.Spider.start_requests()` can now yield items
- Added [`JsonResponse`](../topics/request-response.md)
- Added [`CLOSESPIDER_PAGECOUNT_NO_ITEM`](../topics/extensions.md)

### Modified requirements

- Dropped support for Python 3.8.
  ([#6466](https://github.com/scrapy/scrapy/issues/6466), [#6472](https://github.com/scrapy/scrapy/issues/6472))
- Added support for Python 3.13.
  ([#6166](https://github.com/scrapy/scrapy/issues/6166))
- Minimum versions increased for these dependencies:
  - [Twisted](https://twisted.org/): 18.9.0 → 21.7.0
  - [cryptography](https://cryptography.io/en/latest/): 36.0.0 → 37.0.0
  - [pyOpenSSL](https://www.pyopenssl.org/en/stable/): 21.0.0 → 22.0.0
  - [lxml](https://lxml.de/): 4.4.1 → 4.6.0
- Removed `setuptools` from the dependency list.
  ([#6487](https://github.com/scrapy/scrapy/issues/6487))

### Backward-incompatible changes

- User-defined cookies for HTTPS requests will have the `secure` flag set
  to `True` unless it’s set to `False` explicitly. This is important when
  these cookies are reused in HTTP requests, e.g. after a redirect to an HTTP
  URL.
  ([#6357](https://github.com/scrapy/scrapy/issues/6357))
- The Reppy-based `robots.txt` parser,
  `scrapy.robotstxt.ReppyRobotParser`, was removed, as it doesn’t support
  Python 3.9+.
  ([#5230](https://github.com/scrapy/scrapy/issues/5230), [#6099](https://github.com/scrapy/scrapy/issues/6099), [#6499](https://github.com/scrapy/scrapy/issues/6499))
- The initialization API of `scrapy.pipelines.media.MediaPipeline` and
  its subclasses was improved and it’s possible that some previously working
  usage scenarios will no longer work. It can only affect you if you define
  custom subclasses of `MediaPipeline` or create instances of these
  pipelines via `from_settings()` or `__init__()` calls instead of
  `from_crawler()` calls.

  Previously, `MediaPipeline.from_crawler()` called the `from_settings()`
  method if it existed or the `__init__()` method otherwise, and then did
  some additional initialization using the `crawler` instance. If the
  `from_settings()` method existed (like in `FilesPipeline`) it called
  `__init__()` to create the instance. It wasn’t possible to override
  `from_crawler()` without calling `MediaPipeline.from_crawler()` from it
  which, in turn, couldn’t be called in some cases (including subclasses of
  `FilesPipeline`).

  Now, in line with the general usage of `from_crawler()` and
  `from_settings()` and the deprecation of the latter the recommended
  initialization order is the following one:
  - All `__init__()` methods should take a `crawler` argument. If they
    also take a `settings` argument they should ignore it, using
    `crawler.settings` instead. When they call `__init__()` of the base
    class they should pass the `crawler` argument to it too.
  - A `from_settings()` method shouldn’t be defined. Class-specific
    initialization code should go into either an overridden `from_crawler()`
    method or into `__init__()`.
  - It’s now possible to override `from_crawler()` and it’s not necessary
    to call `MediaPipeline.from_crawler()` in it if other recommendations
    were followed.
  - If pipeline instances were created with `from_settings()` or
    `__init__()` calls (which wasn’t supported even before, as it missed
    important initialization code), they should now be created with
    `from_crawler()` calls.

  ([#6540](https://github.com/scrapy/scrapy/issues/6540))
- The `response_body` argument of `ImagesPipeline.convert_image` is now
  positional-only, as it was changed from optional to required.
  ([#6500](https://github.com/scrapy/scrapy/issues/6500))
- The `convert` argument of `scrapy.utils.conf.build_component_list()`
  is now positional-only, as the preceding argument (`custom`) was removed.
  ([#6500](https://github.com/scrapy/scrapy/issues/6500))
- The `overwrite_output` argument of
  `scrapy.utils.conf.feed_process_params_from_cli()` is now
  positional-only, as the preceding argument (`output_format`) was removed.
  ([#6500](https://github.com/scrapy/scrapy/issues/6500))

### Deprecation removals

- Removed the `scrapy.utils.request.request_fingerprint()` function,
  deprecated in Scrapy 2.7.0.
  ([#6212](https://github.com/scrapy/scrapy/issues/6212), [#6213](https://github.com/scrapy/scrapy/issues/6213))
- Removed support for value `"2.6"` of setting
  `REQUEST_FINGERPRINTER_IMPLEMENTATION`, deprecated in Scrapy 2.7.0.
  ([#6212](https://github.com/scrapy/scrapy/issues/6212), [#6213](https://github.com/scrapy/scrapy/issues/6213))
- [`RFPDupeFilter`](../topics/settings.md) subclasses now require
  supporting the `fingerprinter` parameter in their `__init__` method,
  introduced in Scrapy 2.7.0.
  ([#6102](https://github.com/scrapy/scrapy/issues/6102), [#6113](https://github.com/scrapy/scrapy/issues/6113))
- Removed the `scrapy.downloadermiddlewares.decompression` module,
  deprecated in Scrapy 2.7.0.
  ([#6100](https://github.com/scrapy/scrapy/issues/6100), [#6113](https://github.com/scrapy/scrapy/issues/6113))
- Removed the `scrapy.utils.response.response_httprepr()` function,
  deprecated in Scrapy 2.6.0.
  ([#6111](https://github.com/scrapy/scrapy/issues/6111), [#6116](https://github.com/scrapy/scrapy/issues/6116))
- Spiders with spider-level HTTP authentication, i.e. with the `http_user`
  or `http_pass` attributes, must now define `http_auth_domain` as well,
  which was introduced in Scrapy 2.5.1.
  ([#6103](https://github.com/scrapy/scrapy/issues/6103), [#6113](https://github.com/scrapy/scrapy/issues/6113))
- [Media pipelines](../topics/media-pipeline.md) methods `file_path()`,
  `file_downloaded()`, `get_images()`, `image_downloaded()`,
  `media_downloaded()`, `media_to_download()`, and `thumb_path()` must
  now support an `item` parameter, added in Scrapy 2.4.0.
  ([#6107](https://github.com/scrapy/scrapy/issues/6107), [#6113](https://github.com/scrapy/scrapy/issues/6113))
- The `__init__()` and `from_crawler()` methods of [feed storage
  backend classes](../topics/feed-exports.md "Storages") must now support the keyword-only
  `feed_options` parameter, introduced in Scrapy 2.4.0.
  ([#6105](https://github.com/scrapy/scrapy/issues/6105), [#6113](https://github.com/scrapy/scrapy/issues/6113))
- Removed the `scrapy.loader.common` and `scrapy.loader.processors`
  modules, deprecated in Scrapy 2.3.0.
  ([#6106](https://github.com/scrapy/scrapy/issues/6106), [#6113](https://github.com/scrapy/scrapy/issues/6113))
- Removed the `scrapy.utils.misc.extract_regex()` function, deprecated in
  Scrapy 2.3.0.
  ([#6106](https://github.com/scrapy/scrapy/issues/6106), [#6113](https://github.com/scrapy/scrapy/issues/6113))
- Removed the `scrapy.http.JSONRequest` class, replaced with
  `JsonRequest` in Scrapy 1.8.0.
  ([#6110](https://github.com/scrapy/scrapy/issues/6110), [#6113](https://github.com/scrapy/scrapy/issues/6113))
- `scrapy.utils.log.logformatter_adapter` no longer supports missing
  `args`, `level`, or `msg` parameters, and no longer supports a
  `format` parameter, all scenarios that were deprecated in Scrapy 1.0.0.
  ([#6109](https://github.com/scrapy/scrapy/issues/6109), [#6116](https://github.com/scrapy/scrapy/issues/6116))
- A custom class assigned to the [`SPIDER_LOADER_CLASS`](../topics/settings.md) setting that
  does not implement the `ISpiderLoader` interface
  will now raise a `zope.interface.verify.DoesNotImplement` exception at
  run time. Non-compliant classes have been triggering a deprecation warning
  since Scrapy 1.0.0.
  ([#6101](https://github.com/scrapy/scrapy/issues/6101), [#6113](https://github.com/scrapy/scrapy/issues/6113))
- Removed the `--output-format`/`-t` command line option, deprecated in
  Scrapy 2.1.0. `-O <URI>:<FORMAT>` should be used instead.
  ([#6500](https://github.com/scrapy/scrapy/issues/6500))
- Running [`crawl()`](../topics/api.md) more than once on the same
  [`Crawler`](../topics/api.md) instance, deprecated in Scrapy 2.11.0, now
  raises an exception.
  ([#6500](https://github.com/scrapy/scrapy/issues/6500))
- Subclassing
  [`HttpCompressionMiddleware`](../topics/downloader-middleware.md)
  without support for the `crawler` argument in `__init__()` and without
  a custom `from_crawler()` method, deprecated in Scrapy 2.5.0, is no
  longer allowed.
  ([#6500](https://github.com/scrapy/scrapy/issues/6500))
- Removed the `EXCEPTIONS_TO_RETRY` attribute of
  [`RetryMiddleware`](../topics/downloader-middleware.md), deprecated in
  Scrapy 2.10.0.
  ([#6500](https://github.com/scrapy/scrapy/issues/6500))
- Removed support for [S3 feed exports](../topics/feed-exports.md "S3") without
  the [boto3](https://github.com/boto/boto3) package installed, deprecated in Scrapy 2.10.0.
  ([#6500](https://github.com/scrapy/scrapy/issues/6500))
- Removed the `scrapy.extensions.feedexport._FeedSlot` class, deprecated in
  Scrapy 2.10.0.
  ([#6500](https://github.com/scrapy/scrapy/issues/6500))
- Removed the `scrapy.pipelines.images.NoimagesDrop` exception, deprecated
  in Scrapy 2.8.0.
  ([#6500](https://github.com/scrapy/scrapy/issues/6500))
- The `response_body` argument of `ImagesPipeline.convert_image` is now required,
  not passing it was deprecated in Scrapy 2.8.0.
  ([#6500](https://github.com/scrapy/scrapy/issues/6500))
- Removed the `custom` argument of
  `scrapy.utils.conf.build_component_list()`, deprecated in Scrapy
  2.10.0.
  ([#6500](https://github.com/scrapy/scrapy/issues/6500))
- Removed the `scrapy.utils.reactor.get_asyncio_event_loop_policy()`
  function, deprecated in Scrapy 2.9.0. Use [`asyncio.get_event_loop()`](https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.get_event_loop)
  and related standard library functions instead.
  ([#6500](https://github.com/scrapy/scrapy/issues/6500))

### Deprecations

- The `from_settings()` methods of the [Scrapy components](../topics/components.md) that have them are now deprecated. `from_crawler()`
  should now be used instead. Affected components:
  - [`scrapy.dupefilters.RFPDupeFilter`](../topics/settings.md)
  - `scrapy.mail.MailSender`
  - `scrapy.middleware.MiddlewareManager`
  - `scrapy.core.downloader.contextfactory.ScrapyClientContextFactory`
  - [`scrapy.pipelines.files.FilesPipeline`](../topics/media-pipeline.md)
  - [`scrapy.pipelines.images.ImagesPipeline`](../topics/media-pipeline.md)
  - [`scrapy.spidermiddlewares.urllength.UrlLengthMiddleware`](../topics/spider-middleware.md)

  ([#6540](https://github.com/scrapy/scrapy/issues/6540))
- It’s now deprecated to have a `from_settings()` method but no
  `from_crawler()` method in 3rd-party [Scrapy components](../topics/components.md). You can define a simple `from_crawler()` method
  that calls `cls.from_settings(crawler.settings)` to fix this if you don’t
  want to refactor the code. Note that if you have a `from_crawler()`
  method Scrapy will not call the `from_settings()` method so the latter
  can be removed.
  ([#6540](https://github.com/scrapy/scrapy/issues/6540))
- The initialization API of `scrapy.pipelines.media.MediaPipeline` and
  its subclasses was improved and some old usage scenarios are now deprecated
  (see also the “Backward-incompatible changes” section). Specifically:
  - It’s deprecated to define an `__init__()` method that doesn’t take a
    `crawler` argument.
  - It’s deprecated to call an `__init__()` method without passing a
    `crawler` argument. If it’s passed, it’s also deprecated to pass a
    `settings` argument, which will be ignored anyway.
  - Calling `from_settings()` is deprecated, use `from_crawler()`
    instead.
  - Overriding `from_settings()` is deprecated, override `from_crawler()`
    instead.

  ([#6540](https://github.com/scrapy/scrapy/issues/6540))
- The `REQUEST_FINGERPRINTER_IMPLEMENTATION` setting is now deprecated.
  ([#6212](https://github.com/scrapy/scrapy/issues/6212), [#6213](https://github.com/scrapy/scrapy/issues/6213))
- The `scrapy.utils.misc.create_instance()` function is now deprecated, use
  [`scrapy.utils.misc.build_from_crawler()`](../topics/components.md) instead.
  ([#5523](https://github.com/scrapy/scrapy/issues/5523), [#5884](https://github.com/scrapy/scrapy/issues/5884), [#6162](https://github.com/scrapy/scrapy/issues/6162), [#6169](https://github.com/scrapy/scrapy/issues/6169), [#6540](https://github.com/scrapy/scrapy/issues/6540))
- `scrapy.core.downloader.Downloader._get_slot_key()` is deprecated, use
  `scrapy.core.downloader.Downloader.get_slot_key()` instead.
  ([#6340](https://github.com/scrapy/scrapy/issues/6340), [#6352](https://github.com/scrapy/scrapy/issues/6352))
- `scrapy.utils.defer.process_chain_both()` is now deprecated.
  ([#6397](https://github.com/scrapy/scrapy/issues/6397))
- `scrapy.twisted_version` is now deprecated, you should instead use
  `twisted.version` directly (but note that it’s an
  `incremental.Version` object, not a tuple).
  ([#6509](https://github.com/scrapy/scrapy/issues/6509), [#6512](https://github.com/scrapy/scrapy/issues/6512))
- `scrapy.utils.python.flatten()` and `scrapy.utils.python.iflatten()`
  are now deprecated.
  ([#6517](https://github.com/scrapy/scrapy/issues/6517), [#6519](https://github.com/scrapy/scrapy/issues/6519))
- `scrapy.utils.python.equal_attributes()` is now deprecated.
  ([#6517](https://github.com/scrapy/scrapy/issues/6517), [#6519](https://github.com/scrapy/scrapy/issues/6519))
- `scrapy.utils.request.request_authenticate()` is now deprecated, you
  should instead just set the `Authorization` header directly.
  ([#6517](https://github.com/scrapy/scrapy/issues/6517), [#6519](https://github.com/scrapy/scrapy/issues/6519))
- `scrapy.utils.serialize.ScrapyJSONDecoder` is now deprecated, it didn’t
  contain any code since Scrapy 1.0.0.
  ([#6517](https://github.com/scrapy/scrapy/issues/6517), [#6519](https://github.com/scrapy/scrapy/issues/6519))
- `scrapy.utils.test.assert_samelines()` is now deprecated.
  ([#6517](https://github.com/scrapy/scrapy/issues/6517), [#6519](https://github.com/scrapy/scrapy/issues/6519))
- `scrapy.extensions.feedexport.build_storage()` is now deprecated. You can
  instead call the builder callable directly.
  ([#6540](https://github.com/scrapy/scrapy/issues/6540))
- `scrapy.utils.misc.md5sum()` is now deprecated.
  ([#6264](https://github.com/scrapy/scrapy/issues/6264))

### New features

- `scrapy.Spider.start_requests()` can now yield items.
  ([#5289](https://github.com/scrapy/scrapy/issues/5289), [#6417](https://github.com/scrapy/scrapy/issues/6417))
  > [!NOTE]
  > Some spider middlewares may need to be updated for Scrapy 2.12
  > support before you can use them in combination with the ability to
  > yield items from `start_requests()`.
- Added a new [`Response`](../topics/request-response.md) subclass,
  [`JsonResponse`](../topics/request-response.md), for responses with a [JSON MIME type](https://mimesniff.spec.whatwg.org/#json-mime-type).
  ([#6069](https://github.com/scrapy/scrapy/issues/6069), [#6171](https://github.com/scrapy/scrapy/issues/6171), [#6174](https://github.com/scrapy/scrapy/issues/6174))
- The [`LogStats`](../topics/extensions.md) extension now adds
  `items_per_minute` and `responses_per_minute` to the [stats](../topics/stats.md) when the spider closes.
  ([#4110](https://github.com/scrapy/scrapy/issues/4110), [#4111](https://github.com/scrapy/scrapy/issues/4111))
- Added [`CLOSESPIDER_PAGECOUNT_NO_ITEM`](../topics/extensions.md) which allows closing the
  spider if no items were scraped in a set amount of time.
  ([#6434](https://github.com/scrapy/scrapy/issues/6434))
- User-defined cookies can now include the `secure` field.
  ([#6357](https://github.com/scrapy/scrapy/issues/6357))
- Added component getters to [`Crawler`](../topics/api.md):
  [`get_addon()`](../topics/api.md),
  [`get_downloader_middleware()`](../topics/api.md),
  [`get_extension()`](../topics/api.md),
  [`get_item_pipeline()`](../topics/api.md),
  [`get_spider_middleware()`](../topics/api.md).
  ([#6181](https://github.com/scrapy/scrapy/issues/6181))
- Slot delay updates by the [AutoThrottle extension](../topics/autothrottle.md) based on response latencies can now be disabled for
  specific requests via the [`autothrottle_dont_adjust_delay`](../topics/autothrottle.md) meta
  key.
  ([#6246](https://github.com/scrapy/scrapy/issues/6246), [#6527](https://github.com/scrapy/scrapy/issues/6527))
- If [`SPIDER_LOADER_WARN_ONLY`](../topics/settings.md) is set to `True`,
  [`SpiderLoader`](../topics/api.md) does not raise
  `SyntaxError` but emits a warning instead.
  ([#6483](https://github.com/scrapy/scrapy/issues/6483), [#6484](https://github.com/scrapy/scrapy/issues/6484))
- Added support for multiple-compressed responses (ones with several
  encodings in the `Content-Encoding` header).
  ([#5143](https://github.com/scrapy/scrapy/issues/5143), [#5964](https://github.com/scrapy/scrapy/issues/5964), [#6063](https://github.com/scrapy/scrapy/issues/6063))
- Added support for multiple standard values in [`REFERRER_POLICY`](../topics/spider-middleware.md).
  ([#6381](https://github.com/scrapy/scrapy/issues/6381))
- Added support for [brotlicffi](https://github.com/python-hyper/brotlicffi) (previously named [brotlipy](https://github.com/python-hyper/brotlipy/)). [brotli](https://github.com/google/brotli) is
  still recommended but only [brotlicffi](https://github.com/python-hyper/brotlicffi) works on PyPy.
  ([#6263](https://github.com/scrapy/scrapy/issues/6263), [#6269](https://github.com/scrapy/scrapy/issues/6269))
- Added [`MetadataContract`](../topics/contracts.md) that sets the
  request meta.
  ([#6468](https://github.com/scrapy/scrapy/issues/6468), [#6469](https://github.com/scrapy/scrapy/issues/6469))

### Improvements

- Extended the list of file extensions that
  [`LinkExtractor`](../topics/link-extractors.md)
  ignores by default.
  ([#6074](https://github.com/scrapy/scrapy/issues/6074), [#6125](https://github.com/scrapy/scrapy/issues/6125))
- [`scrapy.utils.httpobj.urlparse_cached()`](../topics/request-response.md) is now used in more places
  instead of [`urllib.parse.urlparse()`](https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlparse).
  ([#6228](https://github.com/scrapy/scrapy/issues/6228), [#6229](https://github.com/scrapy/scrapy/issues/6229))

### Bug fixes

- `MediaPipeline` is now an abstract class and
  its methods that were expected to be overridden in subclasses are now
  abstract methods.
  ([#6365](https://github.com/scrapy/scrapy/issues/6365), [#6368](https://github.com/scrapy/scrapy/issues/6368))
- Fixed handling of invalid `@`-prefixed lines in contract extraction.
  ([#6383](https://github.com/scrapy/scrapy/issues/6383), [#6388](https://github.com/scrapy/scrapy/issues/6388))
- Importing `scrapy.extensions.telnet` no longer installs the default
  reactor.
  ([#6432](https://github.com/scrapy/scrapy/issues/6432))
- Reduced log verbosity for dropped requests that was increased in 2.11.2.
  ([#6433](https://github.com/scrapy/scrapy/issues/6433), [#6475](https://github.com/scrapy/scrapy/issues/6475))

### Documentation

- Added `SECURITY.md` that documents the security policy.
  ([#5364](https://github.com/scrapy/scrapy/issues/5364), [#6051](https://github.com/scrapy/scrapy/issues/6051))
- Example code for [running Scrapy from a script](../topics/practices.md "Run Scrapy from a script") no
  longer imports `twisted.internet.reactor` at the top level, which caused
  problems with non-default reactors when this code was used unmodified.
  ([#6361](https://github.com/scrapy/scrapy/issues/6361), [#6374](https://github.com/scrapy/scrapy/issues/6374))
- Documented the [`SpiderState`](../topics/extensions.md)
  extension.
  ([#6278](https://github.com/scrapy/scrapy/issues/6278), [#6522](https://github.com/scrapy/scrapy/issues/6522))
- Other documentation improvements and fixes.
  ([#5920](https://github.com/scrapy/scrapy/issues/5920),
  [#6094](https://github.com/scrapy/scrapy/issues/6094),
  [#6177](https://github.com/scrapy/scrapy/issues/6177),
  [#6200](https://github.com/scrapy/scrapy/issues/6200),
  [#6207](https://github.com/scrapy/scrapy/issues/6207),
  [#6216](https://github.com/scrapy/scrapy/issues/6216),
  [#6223](https://github.com/scrapy/scrapy/issues/6223),
  [#6317](https://github.com/scrapy/scrapy/issues/6317),
  [#6328](https://github.com/scrapy/scrapy/issues/6328),
  [#6389](https://github.com/scrapy/scrapy/issues/6389),
  [#6394](https://github.com/scrapy/scrapy/issues/6394),
  [#6402](https://github.com/scrapy/scrapy/issues/6402),
  [#6411](https://github.com/scrapy/scrapy/issues/6411),
  [#6427](https://github.com/scrapy/scrapy/issues/6427),
  [#6429](https://github.com/scrapy/scrapy/issues/6429),
  [#6440](https://github.com/scrapy/scrapy/issues/6440),
  [#6448](https://github.com/scrapy/scrapy/issues/6448),
  [#6449](https://github.com/scrapy/scrapy/issues/6449),
  [#6462](https://github.com/scrapy/scrapy/issues/6462),
  [#6497](https://github.com/scrapy/scrapy/issues/6497),
  [#6506](https://github.com/scrapy/scrapy/issues/6506),
  [#6507](https://github.com/scrapy/scrapy/issues/6507),
  [#6524](https://github.com/scrapy/scrapy/issues/6524))

### Quality assurance

- Added `py.typed`, in line with [PEP 561](https://peps.python.org/pep-0561/).
  ([#6058](https://github.com/scrapy/scrapy/issues/6058), [#6059](https://github.com/scrapy/scrapy/issues/6059))
- Fully covered the code with type hints (except for the most complicated
  parts, mostly related to `twisted.web.http` and other Twisted parts
  without type hints).
  ([#5989](https://github.com/scrapy/scrapy/issues/5989),
  [#6097](https://github.com/scrapy/scrapy/issues/6097),
  [#6127](https://github.com/scrapy/scrapy/issues/6127),
  [#6129](https://github.com/scrapy/scrapy/issues/6129),
  [#6130](https://github.com/scrapy/scrapy/issues/6130),
  [#6133](https://github.com/scrapy/scrapy/issues/6133),
  [#6143](https://github.com/scrapy/scrapy/issues/6143),
  [#6191](https://github.com/scrapy/scrapy/issues/6191),
  [#6268](https://github.com/scrapy/scrapy/issues/6268),
  [#6274](https://github.com/scrapy/scrapy/issues/6274),
  [#6275](https://github.com/scrapy/scrapy/issues/6275),
  [#6276](https://github.com/scrapy/scrapy/issues/6276),
  [#6279](https://github.com/scrapy/scrapy/issues/6279),
  [#6325](https://github.com/scrapy/scrapy/issues/6325),
  [#6326](https://github.com/scrapy/scrapy/issues/6326),
  [#6333](https://github.com/scrapy/scrapy/issues/6333),
  [#6335](https://github.com/scrapy/scrapy/issues/6335),
  [#6336](https://github.com/scrapy/scrapy/issues/6336),
  [#6337](https://github.com/scrapy/scrapy/issues/6337),
  [#6341](https://github.com/scrapy/scrapy/issues/6341),
  [#6353](https://github.com/scrapy/scrapy/issues/6353),
  [#6356](https://github.com/scrapy/scrapy/issues/6356),
  [#6370](https://github.com/scrapy/scrapy/issues/6370),
  [#6371](https://github.com/scrapy/scrapy/issues/6371),
  [#6384](https://github.com/scrapy/scrapy/issues/6384),
  [#6385](https://github.com/scrapy/scrapy/issues/6385),
  [#6387](https://github.com/scrapy/scrapy/issues/6387),
  [#6391](https://github.com/scrapy/scrapy/issues/6391),
  [#6395](https://github.com/scrapy/scrapy/issues/6395),
  [#6414](https://github.com/scrapy/scrapy/issues/6414),
  [#6422](https://github.com/scrapy/scrapy/issues/6422),
  [#6460](https://github.com/scrapy/scrapy/issues/6460),
  [#6466](https://github.com/scrapy/scrapy/issues/6466),
  [#6472](https://github.com/scrapy/scrapy/issues/6472),
  [#6494](https://github.com/scrapy/scrapy/issues/6494),
  [#6498](https://github.com/scrapy/scrapy/issues/6498),
  [#6516](https://github.com/scrapy/scrapy/issues/6516))
- Improved [Bandit](https://bandit.readthedocs.io/en/latest/) checks.
  ([#6260](https://github.com/scrapy/scrapy/issues/6260), [#6264](https://github.com/scrapy/scrapy/issues/6264), [#6265](https://github.com/scrapy/scrapy/issues/6265))
- Added [pyupgrade](https://github.com/asottile/pyupgrade) to the `pre-commit` configuration.
  ([#6392](https://github.com/scrapy/scrapy/issues/6392))
- Added `flake8-bugbear`, `flake8-comprehensions`, `flake8-debugger`,
  `flake8-docstrings`, `flake8-string-format` and
  `flake8-type-checking` to the `pre-commit` configuration.
  ([#6406](https://github.com/scrapy/scrapy/issues/6406), [#6413](https://github.com/scrapy/scrapy/issues/6413))
- CI and test improvements and fixes.
  ([#5285](https://github.com/scrapy/scrapy/issues/5285),
  [#5454](https://github.com/scrapy/scrapy/issues/5454),
  [#5997](https://github.com/scrapy/scrapy/issues/5997),
  [#6078](https://github.com/scrapy/scrapy/issues/6078),
  [#6084](https://github.com/scrapy/scrapy/issues/6084),
  [#6087](https://github.com/scrapy/scrapy/issues/6087),
  [#6132](https://github.com/scrapy/scrapy/issues/6132),
  [#6153](https://github.com/scrapy/scrapy/issues/6153),
  [#6154](https://github.com/scrapy/scrapy/issues/6154),
  [#6201](https://github.com/scrapy/scrapy/issues/6201),
  [#6231](https://github.com/scrapy/scrapy/issues/6231),
  [#6232](https://github.com/scrapy/scrapy/issues/6232),
  [#6235](https://github.com/scrapy/scrapy/issues/6235),
  [#6236](https://github.com/scrapy/scrapy/issues/6236),
  [#6242](https://github.com/scrapy/scrapy/issues/6242),
  [#6245](https://github.com/scrapy/scrapy/issues/6245),
  [#6253](https://github.com/scrapy/scrapy/issues/6253),
  [#6258](https://github.com/scrapy/scrapy/issues/6258),
  [#6259](https://github.com/scrapy/scrapy/issues/6259),
  [#6270](https://github.com/scrapy/scrapy/issues/6270),
  [#6272](https://github.com/scrapy/scrapy/issues/6272),
  [#6286](https://github.com/scrapy/scrapy/issues/6286),
  [#6290](https://github.com/scrapy/scrapy/issues/6290),
  [#6296](https://github.com/scrapy/scrapy/issues/6296)
  [#6367](https://github.com/scrapy/scrapy/issues/6367),
  [#6372](https://github.com/scrapy/scrapy/issues/6372),
  [#6403](https://github.com/scrapy/scrapy/issues/6403),
  [#6416](https://github.com/scrapy/scrapy/issues/6416),
  [#6435](https://github.com/scrapy/scrapy/issues/6435),
  [#6489](https://github.com/scrapy/scrapy/issues/6489),
  [#6501](https://github.com/scrapy/scrapy/issues/6501),
  [#6504](https://github.com/scrapy/scrapy/issues/6504),
  [#6511](https://github.com/scrapy/scrapy/issues/6511),
  [#6543](https://github.com/scrapy/scrapy/issues/6543),
  [#6545](https://github.com/scrapy/scrapy/issues/6545))
- Code cleanups.
  ([#6196](https://github.com/scrapy/scrapy/issues/6196),
  [#6197](https://github.com/scrapy/scrapy/issues/6197),
  [#6198](https://github.com/scrapy/scrapy/issues/6198),
  [#6199](https://github.com/scrapy/scrapy/issues/6199),
  [#6254](https://github.com/scrapy/scrapy/issues/6254),
  [#6257](https://github.com/scrapy/scrapy/issues/6257),
  [#6285](https://github.com/scrapy/scrapy/issues/6285),
  [#6305](https://github.com/scrapy/scrapy/issues/6305),
  [#6343](https://github.com/scrapy/scrapy/issues/6343),
  [#6349](https://github.com/scrapy/scrapy/issues/6349),
  [#6386](https://github.com/scrapy/scrapy/issues/6386),
  [#6415](https://github.com/scrapy/scrapy/issues/6415),
  [#6463](https://github.com/scrapy/scrapy/issues/6463),
  [#6470](https://github.com/scrapy/scrapy/issues/6470),
  [#6499](https://github.com/scrapy/scrapy/issues/6499),
  [#6505](https://github.com/scrapy/scrapy/issues/6505),
  [#6510](https://github.com/scrapy/scrapy/issues/6510),
  [#6531](https://github.com/scrapy/scrapy/issues/6531),
  [#6542](https://github.com/scrapy/scrapy/issues/6542))

### Other

- Issue tracker improvements. ([#6066](https://github.com/scrapy/scrapy/issues/6066))

## Scrapy 2.11.2 (2024-05-14)

### Security bug fixes

- Redirects to non-HTTP protocols are no longer followed. Please, see the
  [23j4-mw76-5v7h security advisory](https://github.com/scrapy/scrapy/security/advisories/GHSA-23j4-mw76-5v7h) for more information. ([#457](https://github.com/scrapy/scrapy/issues/457))
- The `Authorization` header is now dropped on redirects to a different
  scheme (`http://` or `https://`) or port, even if the domain is the
  same. Please, see the [4qqq-9vqf-3h3f security advisory](https://github.com/scrapy/scrapy/security/advisories/GHSA-4qqq-9vqf-3h3f) for more
  information.
- When using system proxy settings that are different for `http://` and
  `https://`, redirects to a different URL scheme will now also trigger the
  corresponding change in proxy settings for the redirected request. Please,
  see the [jm3v-qxmh-hxwv security advisory](https://github.com/scrapy/scrapy/security/advisories/GHSA-jm3v-qxmh-hxwv) for more information.
  ([#767](https://github.com/scrapy/scrapy/issues/767))
- [`Spider.allowed_domains`](../topics/spiders.md) is now
  enforced for all requests, and not only requests from spider callbacks.
  ([#1042](https://github.com/scrapy/scrapy/issues/1042), [#2241](https://github.com/scrapy/scrapy/issues/2241), [#6358](https://github.com/scrapy/scrapy/issues/6358))
- [`xmliter_lxml()`](../faq.md) no longer resolves XML
  entities. ([#6265](https://github.com/scrapy/scrapy/issues/6265))
- [defusedxml](https://github.com/tiran/defusedxml) is now used to make
  `scrapy.http.request.rpc.XmlRpcRequest` more secure.
  ([#6250](https://github.com/scrapy/scrapy/issues/6250), [#6251](https://github.com/scrapy/scrapy/issues/6251))

### Deprecations

- `scrapy.spidermiddlewares.offsite.OffsiteMiddleware` (a spider
  middleware) is now deprecated and not enabled by default. The new
  downloader middleware with the same functionality,
  [`scrapy.downloadermiddlewares.offsite.OffsiteMiddleware`](../topics/downloader-middleware.md), is enabled
  instead.
  ([#2241](https://github.com/scrapy/scrapy/issues/2241), [#6358](https://github.com/scrapy/scrapy/issues/6358))

### Bug fixes

- Restored support for [brotlipy](https://github.com/python-hyper/brotlipy/), which had been dropped in Scrapy 2.11.1 in
  favor of [brotli](https://github.com/google/brotli). ([#6261](https://github.com/scrapy/scrapy/issues/6261))
  > [!NOTE]
  > brotlipy is deprecated, both in Scrapy and upstream. Use brotli
  > instead if you can.
- Make [`METAREFRESH_IGNORE_TAGS`](https://docs.scrapy.org/en/latest/topics/downloader-middleware.md#std-setting-METAREFRESH_IGNORE_TAGS) `["noscript"]` by default. This
  prevents
  [`MetaRefreshMiddleware`](../topics/downloader-middleware.md) from
  following redirects that would not be followed by web browsers with
  JavaScript enabled. ([#6342](https://github.com/scrapy/scrapy/issues/6342), [#6347](https://github.com/scrapy/scrapy/issues/6347))
- During [feed export](../topics/feed-exports.md), do not close the
  underlying file from [built-in post-processing plugins](../topics/feed-exports.md "Built-in Plugins").
  ([#5932](https://github.com/scrapy/scrapy/issues/5932), [#6178](https://github.com/scrapy/scrapy/issues/6178), [#6239](https://github.com/scrapy/scrapy/issues/6239))
- [`LinkExtractor`](../topics/link-extractors.md)
  now properly applies the `unique` and `canonicalize` parameters.
  ([#3273](https://github.com/scrapy/scrapy/issues/3273), [#6221](https://github.com/scrapy/scrapy/issues/6221))
- Do not initialize the scheduler disk queue if [`JOBDIR`](../topics/settings.md) is an empty
  string. ([#6121](https://github.com/scrapy/scrapy/issues/6121), [#6124](https://github.com/scrapy/scrapy/issues/6124))
- Fix [`Spider.logger`](../topics/spiders.md) not logging custom extra
  information. ([#6323](https://github.com/scrapy/scrapy/issues/6323), [#6324](https://github.com/scrapy/scrapy/issues/6324))
- `robots.txt` files with a non-UTF-8 encoding no longer prevent parsing
  the UTF-8-compatible (e.g. ASCII) parts of the document.
  ([#6292](https://github.com/scrapy/scrapy/issues/6292), [#6298](https://github.com/scrapy/scrapy/issues/6298))
- `scrapy.http.cookies.WrappedRequest.get_header()` no longer raises an
  exception if `default` is `None`.
  ([#6308](https://github.com/scrapy/scrapy/issues/6308), [#6310](https://github.com/scrapy/scrapy/issues/6310))
- [`Selector`](../topics/selectors.md) now uses
  `scrapy.utils.response.get_base_url()` to determine the base URL of a
  given [`Response`](../topics/request-response.md). ([#6265](https://github.com/scrapy/scrapy/issues/6265))
- The `media_to_download()` method of [media pipelines](../topics/media-pipeline.md) now logs exceptions before stripping them.
  ([#5067](https://github.com/scrapy/scrapy/issues/5067), [#5068](https://github.com/scrapy/scrapy/issues/5068))
- When passing a callback to the [`parse`](../topics/commands.md) command, build the callback
  callable with the right signature.
  ([#6182](https://github.com/scrapy/scrapy/issues/6182))

### Documentation

- Add a FAQ entry about [creating blank requests](../faq.md "How can I make a blank request?").
  ([#6203](https://github.com/scrapy/scrapy/issues/6203), [#6208](https://github.com/scrapy/scrapy/issues/6208))
- Document that `scrapy.Selector.type` can be `"json"`.
  ([#6328](https://github.com/scrapy/scrapy/issues/6328), [#6334](https://github.com/scrapy/scrapy/issues/6334))

### Quality assurance

- Make builds reproducible. ([#5019](https://github.com/scrapy/scrapy/issues/5019), [#6322](https://github.com/scrapy/scrapy/issues/6322))
- Packaging and test fixes.
  ([#6286](https://github.com/scrapy/scrapy/issues/6286), [#6290](https://github.com/scrapy/scrapy/issues/6290), [#6312](https://github.com/scrapy/scrapy/issues/6312), [#6316](https://github.com/scrapy/scrapy/issues/6316), [#6344](https://github.com/scrapy/scrapy/issues/6344))

## Scrapy 2.11.1 (2024-02-14)

Highlights:

- Security bug fixes.
- Support for Twisted >= 23.8.0.
- Documentation improvements.

### Security bug fixes

- Addressed [ReDoS vulnerabilities](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS):
  - `scrapy.utils.iterators.xmliter` is now deprecated in favor of
    [`xmliter_lxml()`](../faq.md), which
    [`XMLFeedSpider`](../topics/spiders.md) now uses.

    To minimize the impact of this change on existing code,
    [`xmliter_lxml()`](../faq.md) now supports indicating
    the node namespace with a prefix in the node name, and big files with
    highly nested trees when using libxml2 2.7+.
  - Fixed regular expressions in the implementation of the
    [`open_in_browser()`](../topics/debug.md) function.

  Please, see the [cc65-xxvf-f7r9 security advisory](https://github.com/scrapy/scrapy/security/advisories/GHSA-cc65-xxvf-f7r9) for more information.
- [`DOWNLOAD_MAXSIZE`](../topics/settings.md) and [`DOWNLOAD_WARNSIZE`](../topics/settings.md) now also apply
  to the decompressed response body. Please, see the [7j7m-v7m3-jqm7 security
  advisory](https://github.com/scrapy/scrapy/security/advisories/GHSA-7j7m-v7m3-jqm7) for more information.
- Also in relation with the [7j7m-v7m3-jqm7 security advisory](https://github.com/scrapy/scrapy/security/advisories/GHSA-7j7m-v7m3-jqm7), the
  deprecated `scrapy.downloadermiddlewares.decompression` module has been
  removed.
- The `Authorization` header is now dropped on redirects to a different
  domain. Please, see the [cw9j-q3vf-hrrv security advisory](https://github.com/scrapy/scrapy/security/advisories/GHSA-cw9j-q3vf-hrrv) for more
  information.

### Modified requirements

- The Twisted dependency is no longer restricted to < 23.8.0. ([#6024](https://github.com/scrapy/scrapy/issues/6024),
  [#6064](https://github.com/scrapy/scrapy/issues/6064), [#6142](https://github.com/scrapy/scrapy/issues/6142))

### Bug fixes

- The OS signal handling code was refactored to no longer use private Twisted
  functions. ([#6024](https://github.com/scrapy/scrapy/issues/6024), [#6064](https://github.com/scrapy/scrapy/issues/6064), [#6112](https://github.com/scrapy/scrapy/issues/6112))

### Documentation

- Improved documentation for [`Crawler`](../topics/api.md) initialization
  changes made in the 2.11.0 release. ([#6057](https://github.com/scrapy/scrapy/issues/6057), [#6147](https://github.com/scrapy/scrapy/issues/6147))
- Extended documentation for [`Request.meta`](../topics/request-response.md).
  ([#5565](https://github.com/scrapy/scrapy/issues/5565))
- Fixed the [`dont_merge_cookies`](../topics/cookies.md) documentation. ([#5936](https://github.com/scrapy/scrapy/issues/5936),
  [#6077](https://github.com/scrapy/scrapy/issues/6077))
- Added a link to Zyte’s export guides to the [feed exports](../topics/feed-exports.md) documentation. ([#6183](https://github.com/scrapy/scrapy/issues/6183))
- Added a missing note about backward-incompatible changes in
  [`PythonItemExporter`](../topics/exporters.md) to the 2.11.0 release notes.
  ([#6060](https://github.com/scrapy/scrapy/issues/6060), [#6081](https://github.com/scrapy/scrapy/issues/6081))
- Added a missing note about removing the deprecated
  `scrapy.utils.boto.is_botocore()` function to the 2.8.0 release notes.
  ([#6056](https://github.com/scrapy/scrapy/issues/6056), [#6061](https://github.com/scrapy/scrapy/issues/6061))
- Other documentation improvements. ([#6128](https://github.com/scrapy/scrapy/issues/6128), [#6144](https://github.com/scrapy/scrapy/issues/6144),
  [#6163](https://github.com/scrapy/scrapy/issues/6163), [#6190](https://github.com/scrapy/scrapy/issues/6190), [#6192](https://github.com/scrapy/scrapy/issues/6192))

### Quality assurance

- Added Python 3.12 to the CI configuration, re-enabled tests that were
  disabled when the pre-release support was added. ([#5985](https://github.com/scrapy/scrapy/issues/5985),
  [#6083](https://github.com/scrapy/scrapy/issues/6083), [#6098](https://github.com/scrapy/scrapy/issues/6098))
- Fixed a test issue on PyPy 7.3.14. ([#6204](https://github.com/scrapy/scrapy/issues/6204), [#6205](https://github.com/scrapy/scrapy/issues/6205))

## Scrapy 2.11.0 (2023-09-18)

Highlights:

- Spiders can now modify [settings](../topics/settings.md) in their
  [`from_crawler()`](../topics/spiders.md) methods, e.g. based on [spider
  arguments](../topics/spiders.md "Spider arguments").
- Periodic logging of stats.

### Backward-incompatible changes

- Most of the initialization of [`scrapy.crawler.Crawler`](../topics/api.md) instances is
  now done in [`crawl()`](../topics/api.md), so the state of
  instances before that method is called is now different compared to older
  Scrapy versions. We do not recommend using the
  [`Crawler`](../topics/api.md) instances before
  [`crawl()`](../topics/api.md) is called. ([#6038](https://github.com/scrapy/scrapy/issues/6038))
- [`scrapy.Spider.from_crawler()`](../topics/spiders.md) is now called before the initialization
  of various components previously initialized in
  `scrapy.crawler.Crawler.__init__()` and before the settings are
  finalized and frozen. This change was needed to allow changing the settings
  in [`scrapy.Spider.from_crawler()`](../topics/spiders.md). If you want to access the final
  setting values and the initialized [`Crawler`](../topics/api.md)
  attributes in the spider code as early as possible you can do this in
  `scrapy.Spider.start_requests()` or in a handler of the
  [`engine_started`](../topics/signals.md) signal. ([#6038](https://github.com/scrapy/scrapy/issues/6038))
- The [`TextResponse.json`](../topics/request-response.md) method now
  requires the response to be in a valid JSON encoding (UTF-8, UTF-16, or
  UTF-32). If you need to deal with JSON documents in an invalid encoding,
  use `json.loads(response.text)` instead. ([#6016](https://github.com/scrapy/scrapy/issues/6016))
- [`PythonItemExporter`](../topics/exporters.md) used the binary output by
  default but it no longer does. ([#6006](https://github.com/scrapy/scrapy/issues/6006), [#6007](https://github.com/scrapy/scrapy/issues/6007))

### Deprecation removals

- Removed the binary export mode of
  [`PythonItemExporter`](../topics/exporters.md), deprecated in Scrapy 1.1.0.
  ([#6006](https://github.com/scrapy/scrapy/issues/6006), [#6007](https://github.com/scrapy/scrapy/issues/6007))
  > [!NOTE]
  > If you are using this Scrapy version on Scrapy Cloud with a stack
  > that includes an older Scrapy version and get a “TypeError:
  > Unexpected options: binary” error, you may need to add
  > `scrapinghub-entrypoint-scrapy >= 0.14.1` to your project
  > requirements or switch to a stack that includes Scrapy 2.11.
- Removed the `CrawlerRunner.spiders` attribute, deprecated in Scrapy
  1.0.0, use `CrawlerRunner.spider_loader` instead. ([#6010](https://github.com/scrapy/scrapy/issues/6010))
- The `scrapy.utils.response.response_httprepr()` function, deprecated in
  Scrapy 2.6.0, has now been removed. ([#6111](https://github.com/scrapy/scrapy/issues/6111))

### Deprecations

- Running [`crawl()`](../topics/api.md) more than once on the same
  [`scrapy.crawler.Crawler`](../topics/api.md) instance is now deprecated. ([#1587](https://github.com/scrapy/scrapy/issues/1587),
  [#6040](https://github.com/scrapy/scrapy/issues/6040))

### New features

- Spiders can now modify settings in their
  [`from_crawler()`](../topics/spiders.md) method, e.g. based on [spider
  arguments](../topics/spiders.md "Spider arguments"). ([#1305](https://github.com/scrapy/scrapy/issues/1305), [#1580](https://github.com/scrapy/scrapy/issues/1580), [#2392](https://github.com/scrapy/scrapy/issues/2392),
  [#3663](https://github.com/scrapy/scrapy/issues/3663), [#6038](https://github.com/scrapy/scrapy/issues/6038))
- Added the [`PeriodicLog`](../topics/extensions.md) extension
  which can be enabled to log stats and/or their differences periodically.
  ([#5926](https://github.com/scrapy/scrapy/issues/5926))
- Optimized the memory usage in [`TextResponse.json`](../topics/request-response.md) by removing unnecessary body decoding.
  ([#5968](https://github.com/scrapy/scrapy/issues/5968), [#6016](https://github.com/scrapy/scrapy/issues/6016))
- Links to `.webp` files are now ignored by [link extractors](../topics/link-extractors.md). ([#6021](https://github.com/scrapy/scrapy/issues/6021))

### Bug fixes

- Fixed logging enabled add-ons. ([#6036](https://github.com/scrapy/scrapy/issues/6036))
- Fixed `MailSender` producing invalid message bodies
  when the `charset` argument is passed to
  `send()`. ([#5096](https://github.com/scrapy/scrapy/issues/5096), [#5118](https://github.com/scrapy/scrapy/issues/5118))
- Fixed an exception when accessing `self.EXCEPTIONS_TO_RETRY` from a
  subclass of [`RetryMiddleware`](../topics/downloader-middleware.md).
  ([#6049](https://github.com/scrapy/scrapy/issues/6049), [#6050](https://github.com/scrapy/scrapy/issues/6050))
- [`scrapy.settings.BaseSettings.getdictorlist()`](../topics/api.md), used to parse
  [`FEED_EXPORT_FIELDS`](../topics/feed-exports.md), now handles tuple values. ([#6011](https://github.com/scrapy/scrapy/issues/6011),
  [#6013](https://github.com/scrapy/scrapy/issues/6013))
- Calls to `datetime.utcnow()`, no longer recommended to be used, have been
  replaced with calls to `datetime.now()` with a timezone. ([#6014](https://github.com/scrapy/scrapy/issues/6014))

### Documentation

- Updated a deprecated function call in a pipeline example. ([#6008](https://github.com/scrapy/scrapy/issues/6008),
  [#6009](https://github.com/scrapy/scrapy/issues/6009))

### Quality assurance

- Extended typing hints. ([#6003](https://github.com/scrapy/scrapy/issues/6003), [#6005](https://github.com/scrapy/scrapy/issues/6005), [#6031](https://github.com/scrapy/scrapy/issues/6031),
  [#6034](https://github.com/scrapy/scrapy/issues/6034))
- Pinned [brotli](https://github.com/google/brotli) to 1.0.9 for the PyPy tests as 1.1.0 breaks them.
  ([#6044](https://github.com/scrapy/scrapy/issues/6044), [#6045](https://github.com/scrapy/scrapy/issues/6045))
- Other CI and pre-commit improvements. ([#6002](https://github.com/scrapy/scrapy/issues/6002), [#6013](https://github.com/scrapy/scrapy/issues/6013),
  [#6046](https://github.com/scrapy/scrapy/issues/6046))

## Scrapy 2.10.1 (2023-08-30)

Marked `Twisted >= 23.8.0` as unsupported. ([#6024](https://github.com/scrapy/scrapy/issues/6024), [#6026](https://github.com/scrapy/scrapy/issues/6026))

## Scrapy 2.10.0 (2023-08-04)

Highlights:

- Added Python 3.12 support, dropped Python 3.7 support.
- The new add-ons framework simplifies configuring 3rd-party components that
  support it.
- Exceptions to retry can now be configured.
- Many fixes and improvements for feed exports.

### Modified requirements

- Dropped support for Python 3.7. ([#5953](https://github.com/scrapy/scrapy/issues/5953))
- Added support for the upcoming Python 3.12. ([#5984](https://github.com/scrapy/scrapy/issues/5984))
- Minimum versions increased for these dependencies:
  - [lxml](https://lxml.de/): 4.3.0 → 4.4.1
  - [cryptography](https://cryptography.io/en/latest/): 3.4.6 → 36.0.0
- `pkg_resources` is no longer used. ([#5956](https://github.com/scrapy/scrapy/issues/5956), [#5958](https://github.com/scrapy/scrapy/issues/5958))
- [boto3](https://github.com/boto/boto3) is now recommended instead of [botocore](https://github.com/boto/botocore) for exporting to S3.
  ([#5833](https://github.com/scrapy/scrapy/issues/5833)).

### Backward-incompatible changes

- The value of the [`FEED_STORE_EMPTY`](../topics/feed-exports.md) setting is now `True`
  instead of `False`. In earlier Scrapy versions empty files were created
  even when this setting was `False` (which was a bug that is now fixed),
  so the new default should keep the old behavior. ([#872](https://github.com/scrapy/scrapy/issues/872),
  [#5847](https://github.com/scrapy/scrapy/issues/5847))

### Deprecation removals

- When a function is assigned to the [`FEED_URI_PARAMS`](../topics/feed-exports.md) setting,
  returning `None` or modifying the `params` input parameter, deprecated
  in Scrapy 2.6, is no longer supported. ([#5994](https://github.com/scrapy/scrapy/issues/5994), [#5996](https://github.com/scrapy/scrapy/issues/5996))
- The `scrapy.utils.reqser` module, deprecated in Scrapy 2.6, is removed.
  ([#5994](https://github.com/scrapy/scrapy/issues/5994), [#5996](https://github.com/scrapy/scrapy/issues/5996))
- The `scrapy.squeues` classes `PickleFifoDiskQueueNonRequest`,
  `PickleLifoDiskQueueNonRequest`, `MarshalFifoDiskQueueNonRequest`,
  and `MarshalLifoDiskQueueNonRequest`, deprecated in
  Scrapy 2.6, are removed. ([#5994](https://github.com/scrapy/scrapy/issues/5994), [#5996](https://github.com/scrapy/scrapy/issues/5996))
- The property `open_spiders` and the methods `has_capacity` and
  `schedule` of [`scrapy.core.engine.ExecutionEngine`](../topics/api.md),
  deprecated in Scrapy 2.6, are removed. ([#5994](https://github.com/scrapy/scrapy/issues/5994), [#5998](https://github.com/scrapy/scrapy/issues/5998))
- Passing a `spider` argument to the
  `spider_is_idle()`,
  `crawl()` and
  `download()` methods of
  [`scrapy.core.engine.ExecutionEngine`](../topics/api.md), deprecated in Scrapy 2.6, is
  no longer supported. ([#5994](https://github.com/scrapy/scrapy/issues/5994), [#5998](https://github.com/scrapy/scrapy/issues/5998))

### Deprecations

- `scrapy.utils.datatypes.CaselessDict` is deprecated, use
  `scrapy.utils.datatypes.CaseInsensitiveDict` instead.
  ([#5146](https://github.com/scrapy/scrapy/issues/5146))
- Passing the `custom` argument to
  `scrapy.utils.conf.build_component_list()` is deprecated, it was used
  in the past to merge `FOO` and `FOO_BASE` setting values but now Scrapy
  uses [`scrapy.settings.BaseSettings.getwithbase()`](../topics/api.md) to do the same.
  Code that uses this argument and cannot be switched to `getwithbase()`
  can be switched to merging the values explicitly. ([#5726](https://github.com/scrapy/scrapy/issues/5726),
  [#5923](https://github.com/scrapy/scrapy/issues/5923))

### New features

- Added support for [Scrapy add-ons](../topics/addons.md). ([#5950](https://github.com/scrapy/scrapy/issues/5950))
- Added the [`RETRY_EXCEPTIONS`](../topics/downloader-middleware.md) setting that configures which
  exceptions will be retried by
  [`RetryMiddleware`](../topics/downloader-middleware.md).
  ([#2701](https://github.com/scrapy/scrapy/issues/2701), [#5929](https://github.com/scrapy/scrapy/issues/5929))
- Added the possiiblity to close the spider if no items were produced in the
  specified time, configured by [`CLOSESPIDER_TIMEOUT_NO_ITEM`](../topics/extensions.md).
  ([#5979](https://github.com/scrapy/scrapy/issues/5979))
- Added support for the [`AWS_REGION_NAME`](../topics/settings.md) setting to feed exports.
  ([#5980](https://github.com/scrapy/scrapy/issues/5980))
- Added support for using [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) objects that refer to
  absolute Windows paths in the [`FEEDS`](../topics/feed-exports.md) setting. ([#5939](https://github.com/scrapy/scrapy/issues/5939))

### Bug fixes

- Fixed creating empty feeds even with `FEED_STORE_EMPTY=False`.
  ([#872](https://github.com/scrapy/scrapy/issues/872), [#5847](https://github.com/scrapy/scrapy/issues/5847))
- Fixed using absolute Windows paths when specifying output files.
  ([#5969](https://github.com/scrapy/scrapy/issues/5969), [#5971](https://github.com/scrapy/scrapy/issues/5971))
- Fixed problems with uploading large files to S3 by switching to multipart
  uploads (requires [boto3](https://github.com/boto/boto3)). ([#960](https://github.com/scrapy/scrapy/issues/960), [#5735](https://github.com/scrapy/scrapy/issues/5735), [#5833](https://github.com/scrapy/scrapy/issues/5833))
- Fixed the JSON exporter writing extra commas when some exceptions occur.
  ([#3090](https://github.com/scrapy/scrapy/issues/3090), [#5952](https://github.com/scrapy/scrapy/issues/5952))
- Fixed the “read of closed file” error in the CSV exporter. ([#5043](https://github.com/scrapy/scrapy/issues/5043),
  [#5705](https://github.com/scrapy/scrapy/issues/5705))
- Fixed an error when a component added by the class object throws
  [`NotConfigured`](../topics/exceptions.md) with a message. ([#5950](https://github.com/scrapy/scrapy/issues/5950),
  [#5992](https://github.com/scrapy/scrapy/issues/5992))
- Added the missing [`scrapy.settings.BaseSettings.pop()`](../topics/api.md) method.
  ([#5959](https://github.com/scrapy/scrapy/issues/5959), [#5960](https://github.com/scrapy/scrapy/issues/5960), [#5963](https://github.com/scrapy/scrapy/issues/5963))
- Added `CaseInsensitiveDict` as a replacement
  for `CaselessDict` that fixes some API
  inconsistencies. ([#5146](https://github.com/scrapy/scrapy/issues/5146))

### Documentation

- Documented [`scrapy.Spider.update_settings()`](../topics/spiders.md). ([#5745](https://github.com/scrapy/scrapy/issues/5745),
  [#5846](https://github.com/scrapy/scrapy/issues/5846))
- Documented possible problems with early Twisted reactor installation and
  their solutions. ([#5981](https://github.com/scrapy/scrapy/issues/5981), [#6000](https://github.com/scrapy/scrapy/issues/6000))
- Added examples of making additional requests in callbacks. ([#5927](https://github.com/scrapy/scrapy/issues/5927))
- Improved the feed export docs. ([#5579](https://github.com/scrapy/scrapy/issues/5579), [#5931](https://github.com/scrapy/scrapy/issues/5931))
- Clarified the docs about request objects on redirection. ([#5707](https://github.com/scrapy/scrapy/issues/5707),
  [#5937](https://github.com/scrapy/scrapy/issues/5937))

### Quality assurance

- Added support for running tests against the installed Scrapy version.
  ([#4914](https://github.com/scrapy/scrapy/issues/4914), [#5949](https://github.com/scrapy/scrapy/issues/5949))
- Extended typing hints. ([#5925](https://github.com/scrapy/scrapy/issues/5925), [#5977](https://github.com/scrapy/scrapy/issues/5977))
- Fixed the `test_utils_asyncio.AsyncioTest.test_set_asyncio_event_loop`
  test. ([#5951](https://github.com/scrapy/scrapy/issues/5951))
- Fixed the `test_feedexport.BatchDeliveriesTest.test_batch_path_differ`
  test on Windows. ([#5847](https://github.com/scrapy/scrapy/issues/5847))
- Enabled CI runs for Python 3.11 on Windows. ([#5999](https://github.com/scrapy/scrapy/issues/5999))
- Simplified skipping tests that depend on `uvloop`. ([#5984](https://github.com/scrapy/scrapy/issues/5984))
- Fixed the `extra-deps-pinned` tox env. ([#5948](https://github.com/scrapy/scrapy/issues/5948))
- Implemented cleanups. ([#5965](https://github.com/scrapy/scrapy/issues/5965), [#5986](https://github.com/scrapy/scrapy/issues/5986))

## Scrapy 2.9.0 (2023-05-08)

Highlights:

- Per-domain download settings.
- Compatibility with new [cryptography](https://cryptography.io/en/latest/) and new [parsel](https://github.com/scrapy/parsel).
- JMESPath selectors from the new [parsel](https://github.com/scrapy/parsel).
- Bug fixes.

### Deprecations

- `scrapy.extensions.feedexport._FeedSlot` is renamed to
  `scrapy.extensions.feedexport.FeedSlot` and the old name is
  deprecated. ([#5876](https://github.com/scrapy/scrapy/issues/5876))

### New features

- Settings corresponding to [`DOWNLOAD_DELAY`](../topics/settings.md),
  [`CONCURRENT_REQUESTS_PER_DOMAIN`](../topics/settings.md) and
  `RANDOMIZE_DOWNLOAD_DELAY` can now be set on a per-domain basis
  via the new [`DOWNLOAD_SLOTS`](../topics/settings.md) setting. ([#5328](https://github.com/scrapy/scrapy/issues/5328))
- Added [`TextResponse.jmespath()`](../topics/request-response.md), a shortcut for JMESPath selectors
  available since [parsel](https://github.com/scrapy/parsel) 1.8.1. ([#5894](https://github.com/scrapy/scrapy/issues/5894), [#5915](https://github.com/scrapy/scrapy/issues/5915))
- Added [`feed_slot_closed`](../topics/signals.md) and [`feed_exporter_closed`](../topics/signals.md)
  signals. ([#5876](https://github.com/scrapy/scrapy/issues/5876))
- Added `scrapy.utils.request.request_to_curl()`, a function to produce a
  curl command from a [`Request`](../topics/request-response.md) object. ([#5892](https://github.com/scrapy/scrapy/issues/5892))
- Values of [`FILES_STORE`](../topics/media-pipeline.md) and [`IMAGES_STORE`](../topics/media-pipeline.md) can now be
  [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) instances. ([#5801](https://github.com/scrapy/scrapy/issues/5801))

### Bug fixes

- Fixed a warning with Parsel 1.8.1+. ([#5903](https://github.com/scrapy/scrapy/issues/5903), [#5918](https://github.com/scrapy/scrapy/issues/5918))
- Fixed an error when using feed postprocessing with S3 storage.
  ([#5500](https://github.com/scrapy/scrapy/issues/5500), [#5581](https://github.com/scrapy/scrapy/issues/5581))
- Added the missing [`scrapy.settings.BaseSettings.setdefault()`](../topics/api.md) method.
  ([#5811](https://github.com/scrapy/scrapy/issues/5811), [#5821](https://github.com/scrapy/scrapy/issues/5821))
- Fixed an error when using [cryptography](https://cryptography.io/en/latest/) 40.0.0+ and
  [`DOWNLOADER_CLIENT_TLS_VERBOSE_LOGGING`](../topics/settings.md) is enabled.
  ([#5857](https://github.com/scrapy/scrapy/issues/5857), [#5858](https://github.com/scrapy/scrapy/issues/5858))
- The checksums returned by [`FilesPipeline`](../topics/media-pipeline.md)
  for files on Google Cloud Storage are no longer Base64-encoded.
  ([#5874](https://github.com/scrapy/scrapy/issues/5874), [#5891](https://github.com/scrapy/scrapy/issues/5891))
- `scrapy.utils.request.request_from_curl()` now supports $-prefixed
  string values for the curl `--data-raw` argument, which are produced by
  browsers for data that includes certain symbols. ([#5899](https://github.com/scrapy/scrapy/issues/5899),
  [#5901](https://github.com/scrapy/scrapy/issues/5901))
- The [`parse`](../topics/commands.md) command now also works with async generator callbacks.
  ([#5819](https://github.com/scrapy/scrapy/issues/5819), [#5824](https://github.com/scrapy/scrapy/issues/5824))
- The [`genspider`](../topics/commands.md) command now properly works with HTTPS URLs.
  ([#3553](https://github.com/scrapy/scrapy/issues/3553), [#5808](https://github.com/scrapy/scrapy/issues/5808))
- Improved handling of asyncio loops. ([#5831](https://github.com/scrapy/scrapy/issues/5831), [#5832](https://github.com/scrapy/scrapy/issues/5832))
- [`LinkExtractor`](../topics/link-extractors.md)
  now skips certain malformed URLs instead of raising an exception.
  ([#5881](https://github.com/scrapy/scrapy/issues/5881))
- `scrapy.utils.python.get_func_args()` now supports more types of
  callables. ([#5872](https://github.com/scrapy/scrapy/issues/5872), [#5885](https://github.com/scrapy/scrapy/issues/5885))
- Fixed an error when processing non-UTF8 values of `Content-Type` headers.
  ([#5914](https://github.com/scrapy/scrapy/issues/5914), [#5917](https://github.com/scrapy/scrapy/issues/5917))
- Fixed an error breaking user handling of send failures in
  `scrapy.mail.MailSender.send()`. ([#1611](https://github.com/scrapy/scrapy/issues/1611), [#5880](https://github.com/scrapy/scrapy/issues/5880))

### Documentation

- Expanded contributing docs. ([#5109](https://github.com/scrapy/scrapy/issues/5109), [#5851](https://github.com/scrapy/scrapy/issues/5851))
- Added [blacken-docs](https://github.com/adamchainz/blacken-docs) to pre-commit and reformatted the docs with it.
  ([#5813](https://github.com/scrapy/scrapy/issues/5813), [#5816](https://github.com/scrapy/scrapy/issues/5816))
- Fixed a JS issue. ([#5875](https://github.com/scrapy/scrapy/issues/5875), [#5877](https://github.com/scrapy/scrapy/issues/5877))
- Fixed `make htmlview`. ([#5878](https://github.com/scrapy/scrapy/issues/5878), [#5879](https://github.com/scrapy/scrapy/issues/5879))
- Fixed typos and other small errors. ([#5827](https://github.com/scrapy/scrapy/issues/5827), [#5839](https://github.com/scrapy/scrapy/issues/5839),
  [#5883](https://github.com/scrapy/scrapy/issues/5883), [#5890](https://github.com/scrapy/scrapy/issues/5890), [#5895](https://github.com/scrapy/scrapy/issues/5895), [#5904](https://github.com/scrapy/scrapy/issues/5904))

### Quality assurance

- Extended typing hints. ([#5805](https://github.com/scrapy/scrapy/issues/5805), [#5889](https://github.com/scrapy/scrapy/issues/5889), [#5896](https://github.com/scrapy/scrapy/issues/5896))
- Tests for most of the examples in the docs are now run as a part of CI,
  found problems were fixed. ([#5816](https://github.com/scrapy/scrapy/issues/5816), [#5826](https://github.com/scrapy/scrapy/issues/5826), [#5919](https://github.com/scrapy/scrapy/issues/5919))
- Removed usage of deprecated Python classes. ([#5849](https://github.com/scrapy/scrapy/issues/5849))
- Silenced `include-ignored` warnings from coverage. ([#5820](https://github.com/scrapy/scrapy/issues/5820))
- Fixed a random failure of the `test_feedexport.test_batch_path_differ`
  test. ([#5855](https://github.com/scrapy/scrapy/issues/5855), [#5898](https://github.com/scrapy/scrapy/issues/5898))
- Updated docstrings to match output produced by [parsel](https://github.com/scrapy/parsel) 1.8.1 so that they
  don’t cause test failures. ([#5902](https://github.com/scrapy/scrapy/issues/5902), [#5919](https://github.com/scrapy/scrapy/issues/5919))
- Other CI and pre-commit improvements. ([#5802](https://github.com/scrapy/scrapy/issues/5802), [#5823](https://github.com/scrapy/scrapy/issues/5823),
  [#5908](https://github.com/scrapy/scrapy/issues/5908))

## Scrapy 2.8.0 (2023-02-02)

This is a maintenance release, with minor features, bug fixes, and cleanups.

### Deprecation removals

- The `scrapy.utils.gz.read1` function, deprecated in Scrapy 2.0, has now
  been removed. Use the [`read1()`](https://docs.python.org/3/library/io.html#io.BufferedIOBase.read1) method of
  [`GzipFile`](https://docs.python.org/3/library/gzip.html#gzip.GzipFile) instead.
  ([#5719](https://github.com/scrapy/scrapy/issues/5719))
- The `scrapy.utils.python.to_native_str` function, deprecated in Scrapy
  2.0, has now been removed. Use `scrapy.utils.python.to_unicode()`
  instead.
  ([#5719](https://github.com/scrapy/scrapy/issues/5719))
- The `scrapy.utils.python.MutableChain.next` method, deprecated in Scrapy
  2.0, has now been removed. Use
  `__next__()` instead.
  ([#5719](https://github.com/scrapy/scrapy/issues/5719))
- The `scrapy.linkextractors.FilteringLinkExtractor` class, deprecated
  in Scrapy 2.0, has now been removed. Use
  [`LinkExtractor`](../topics/link-extractors.md)
  instead.
  ([#5720](https://github.com/scrapy/scrapy/issues/5720))
- Support for using environment variables prefixed with `SCRAPY_` to
  override settings, deprecated in Scrapy 2.0, has now been removed.
  ([#5724](https://github.com/scrapy/scrapy/issues/5724))
- Support for the `noconnect` query string argument in proxy URLs,
  deprecated in Scrapy 2.0, has now been removed. We expect proxies that used
  to need it to work fine without it.
  ([#5731](https://github.com/scrapy/scrapy/issues/5731))
- The `scrapy.utils.python.retry_on_eintr` function, deprecated in Scrapy
  2.3, has now been removed.
  ([#5719](https://github.com/scrapy/scrapy/issues/5719))
- The `scrapy.utils.python.WeakKeyCache` class, deprecated in Scrapy 2.4,
  has now been removed.
  ([#5719](https://github.com/scrapy/scrapy/issues/5719))
- The `scrapy.utils.boto.is_botocore()` function, deprecated in Scrapy 2.4,
  has now been removed.
  ([#5719](https://github.com/scrapy/scrapy/issues/5719))

### Deprecations

- `scrapy.pipelines.images.NoimagesDrop` is now deprecated.
  ([#5368](https://github.com/scrapy/scrapy/issues/5368), [#5489](https://github.com/scrapy/scrapy/issues/5489))
- `ImagesPipeline.convert_image` must now accept a
  `response_body` parameter.
  ([#3055](https://github.com/scrapy/scrapy/issues/3055), [#3689](https://github.com/scrapy/scrapy/issues/3689), [#4753](https://github.com/scrapy/scrapy/issues/4753))

### New features

- Applied [black](https://black.readthedocs.io/en/stable/) coding style to files generated with the
  [`genspider`](../topics/commands.md) and [`startproject`](../topics/commands.md) commands.
  ([#5809](https://github.com/scrapy/scrapy/issues/5809), [#5814](https://github.com/scrapy/scrapy/issues/5814))
- [`FEED_EXPORT_ENCODING`](../topics/feed-exports.md) is now set to `"utf-8"` in the
  `settings.py` file that the [`startproject`](../topics/commands.md) command generates.
  With this value, JSON exports won’t force the use of escape sequences for
  non-ASCII characters.
  ([#5797](https://github.com/scrapy/scrapy/issues/5797), [#5800](https://github.com/scrapy/scrapy/issues/5800))
- The [`MemoryUsage`](../topics/extensions.md) extension now logs the
  peak memory usage during checks, and the binary unit MiB is now used to
  avoid confusion.
  ([#5717](https://github.com/scrapy/scrapy/issues/5717), [#5722](https://github.com/scrapy/scrapy/issues/5722), [#5727](https://github.com/scrapy/scrapy/issues/5727))
- The `callback` parameter of [`Request`](../topics/request-response.md) can now be set
  to [`scrapy.http.request.NO_CALLBACK()`](../topics/request-response.md), to distinguish it from
  `None`, as the latter indicates that the default spider callback
  ([`parse()`](../topics/spiders.md)) is to be used.
  ([#5798](https://github.com/scrapy/scrapy/issues/5798))

### Bug fixes

- Enabled unsafe legacy SSL renegotiation to fix access to some outdated
  websites.
  ([#5491](https://github.com/scrapy/scrapy/issues/5491), [#5790](https://github.com/scrapy/scrapy/issues/5790))
- Fixed STARTTLS-based email delivery not working with Twisted 21.2.0 and
  better.
  ([#5386](https://github.com/scrapy/scrapy/issues/5386), [#5406](https://github.com/scrapy/scrapy/issues/5406))
- Fixed the `finish_exporting()` method of [item exporters](../topics/exporters.md) not being called for empty files.
  ([#5537](https://github.com/scrapy/scrapy/issues/5537), [#5758](https://github.com/scrapy/scrapy/issues/5758))
- Fixed HTTP/2 responses getting only the last value for a header when
  multiple headers with the same name are received.
  ([#5777](https://github.com/scrapy/scrapy/issues/5777))
- Fixed an exception raised by the [`shell`](../topics/commands.md) command on some cases
  when [using asyncio](../topics/asyncio.md).
  ([#5740](https://github.com/scrapy/scrapy/issues/5740), [#5742](https://github.com/scrapy/scrapy/issues/5742), [#5748](https://github.com/scrapy/scrapy/issues/5748), [#5759](https://github.com/scrapy/scrapy/issues/5759), [#5760](https://github.com/scrapy/scrapy/issues/5760),
  [#5771](https://github.com/scrapy/scrapy/issues/5771))
- When using [`CrawlSpider`](../topics/spiders.md), callback keyword arguments
  (`cb_kwargs`) added to a request in the `process_request` callback of a
  [`Rule`](../topics/spiders.md) will no longer be ignored.
  ([#5699](https://github.com/scrapy/scrapy/issues/5699))
- The [images pipeline](../topics/media-pipeline.md "Using the Images Pipeline") no longer re-encodes JPEG
  files.
  ([#3055](https://github.com/scrapy/scrapy/issues/3055), [#3689](https://github.com/scrapy/scrapy/issues/3689), [#4753](https://github.com/scrapy/scrapy/issues/4753))
- Fixed the handling of transparent WebP images by the [images pipeline](../topics/media-pipeline.md "Using the Images Pipeline").
  ([#3072](https://github.com/scrapy/scrapy/issues/3072), [#5766](https://github.com/scrapy/scrapy/issues/5766), [#5767](https://github.com/scrapy/scrapy/issues/5767))
- `scrapy.shell.inspect_response()` no longer inhibits `SIGINT`
  (Ctrl+C).
  ([#2918](https://github.com/scrapy/scrapy/issues/2918))
- [`LinkExtractor`](../topics/link-extractors.md)
  with `unique=False` no longer filters out links that have identical URL
  *and* text.
  ([#3798](https://github.com/scrapy/scrapy/issues/3798), [#3799](https://github.com/scrapy/scrapy/issues/3799), [#4695](https://github.com/scrapy/scrapy/issues/4695), [#5458](https://github.com/scrapy/scrapy/issues/5458))
- [`RobotsTxtMiddleware`](../topics/downloader-middleware.md) now
  ignores URL protocols that do not support `robots.txt` (`data://`,
  `file://`).
  ([#5807](https://github.com/scrapy/scrapy/issues/5807))
- Silenced the `filelock` debug log messages introduced in Scrapy 2.6.
  ([#5753](https://github.com/scrapy/scrapy/issues/5753), [#5754](https://github.com/scrapy/scrapy/issues/5754))
- Fixed the output of `scrapy -h` showing an unintended `**commands**`
  line.
  ([#5709](https://github.com/scrapy/scrapy/issues/5709), [#5711](https://github.com/scrapy/scrapy/issues/5711), [#5712](https://github.com/scrapy/scrapy/issues/5712))
- Made the active project indication in the output of [commands](../topics/commands.md) more clear.
  ([#5715](https://github.com/scrapy/scrapy/issues/5715))

### Documentation

- Documented how to [debug spiders from Visual Studio Code](../topics/debug.md "Visual Studio Code").
  ([#5721](https://github.com/scrapy/scrapy/issues/5721))
- Documented how [`DOWNLOAD_DELAY`](../topics/settings.md) affects per-domain concurrency.
  ([#5083](https://github.com/scrapy/scrapy/issues/5083), [#5540](https://github.com/scrapy/scrapy/issues/5540))
- Improved consistency.
  ([#5761](https://github.com/scrapy/scrapy/issues/5761))
- Fixed typos.
  ([#5714](https://github.com/scrapy/scrapy/issues/5714), [#5744](https://github.com/scrapy/scrapy/issues/5744), [#5764](https://github.com/scrapy/scrapy/issues/5764))

### Quality assurance

- Applied [black coding style](../contributing.md "Coding style"), sorted import statements,
  and introduced [pre-commit](../contributing.md).
  ([#4654](https://github.com/scrapy/scrapy/issues/4654), [#4658](https://github.com/scrapy/scrapy/issues/4658), [#5734](https://github.com/scrapy/scrapy/issues/5734), [#5737](https://github.com/scrapy/scrapy/issues/5737), [#5806](https://github.com/scrapy/scrapy/issues/5806),
  [#5810](https://github.com/scrapy/scrapy/issues/5810))
- Switched from [`os.path`](https://docs.python.org/3/library/os.path.html#module-os.path) to [`pathlib`](https://docs.python.org/3/library/pathlib.html#module-pathlib).
  ([#4916](https://github.com/scrapy/scrapy/issues/4916), [#4497](https://github.com/scrapy/scrapy/issues/4497), [#5682](https://github.com/scrapy/scrapy/issues/5682))
- Addressed many issues reported by Pylint.
  ([#5677](https://github.com/scrapy/scrapy/issues/5677))
- Improved code readability.
  ([#5736](https://github.com/scrapy/scrapy/issues/5736))
- Improved package metadata.
  ([#5768](https://github.com/scrapy/scrapy/issues/5768))
- Removed direct invocations of `setup.py`.
  ([#5774](https://github.com/scrapy/scrapy/issues/5774), [#5776](https://github.com/scrapy/scrapy/issues/5776))
- Removed unnecessary [`OrderedDict`](https://docs.python.org/3/library/collections.html#collections.OrderedDict) usages.
  ([#5795](https://github.com/scrapy/scrapy/issues/5795))
- Removed unnecessary `__str__` definitions.
  ([#5150](https://github.com/scrapy/scrapy/issues/5150))
- Removed obsolete code and comments.
  ([#5725](https://github.com/scrapy/scrapy/issues/5725), [#5729](https://github.com/scrapy/scrapy/issues/5729), [#5730](https://github.com/scrapy/scrapy/issues/5730), [#5732](https://github.com/scrapy/scrapy/issues/5732))
- Fixed test and CI issues.
  ([#5749](https://github.com/scrapy/scrapy/issues/5749), [#5750](https://github.com/scrapy/scrapy/issues/5750), [#5756](https://github.com/scrapy/scrapy/issues/5756), [#5762](https://github.com/scrapy/scrapy/issues/5762), [#5765](https://github.com/scrapy/scrapy/issues/5765),
  [#5780](https://github.com/scrapy/scrapy/issues/5780), [#5781](https://github.com/scrapy/scrapy/issues/5781), [#5782](https://github.com/scrapy/scrapy/issues/5782), [#5783](https://github.com/scrapy/scrapy/issues/5783), [#5785](https://github.com/scrapy/scrapy/issues/5785),
  [#5786](https://github.com/scrapy/scrapy/issues/5786))

## Scrapy 2.7.1 (2022-11-02)

### New features

- Relaxed the restriction introduced in 2.6.2 so that the
  `Proxy-Authorization` header can again be set explicitly, as long as the
  proxy URL in the [`proxy`](../topics/downloader-middleware.md) metadata has no other credentials, and
  for as long as that proxy URL remains the same; this restores compatibility
  with scrapy-zyte-smartproxy 2.1.0 and older ([#5626](https://github.com/scrapy/scrapy/issues/5626)).

### Bug fixes

- Using `-O`/`--overwrite-output` and `-t`/`--output-format` options
  together now produces an error instead of ignoring the former option
  ([#5516](https://github.com/scrapy/scrapy/issues/5516), [#5605](https://github.com/scrapy/scrapy/issues/5605)).
- Replaced deprecated [`asyncio`](https://docs.python.org/3/library/asyncio.html#module-asyncio) APIs that implicitly use the current
  event loop with code that explicitly requests a loop from the event loop
  policy ([#5685](https://github.com/scrapy/scrapy/issues/5685), [#5689](https://github.com/scrapy/scrapy/issues/5689)).
- Fixed uses of deprecated Scrapy APIs in Scrapy itself ([#5588](https://github.com/scrapy/scrapy/issues/5588),
  [#5589](https://github.com/scrapy/scrapy/issues/5589)).
- Fixed uses of a deprecated Pillow API ([#5684](https://github.com/scrapy/scrapy/issues/5684), [#5692](https://github.com/scrapy/scrapy/issues/5692)).
- Improved code that checks if generators return values, so that it no longer
  fails on decorated methods and partial methods ([#5323](https://github.com/scrapy/scrapy/issues/5323),
  [#5592](https://github.com/scrapy/scrapy/issues/5592), [#5599](https://github.com/scrapy/scrapy/issues/5599), [#5691](https://github.com/scrapy/scrapy/issues/5691)).

### Documentation

- Upgraded the Code of Conduct to Contributor Covenant v2.1 ([#5698](https://github.com/scrapy/scrapy/issues/5698)).
- Fixed typos ([#5681](https://github.com/scrapy/scrapy/issues/5681), [#5694](https://github.com/scrapy/scrapy/issues/5694)).

### Quality assurance

- Re-enabled some erroneously disabled flake8 checks ([#5688](https://github.com/scrapy/scrapy/issues/5688)).
- Ignored harmless deprecation warnings from [`typing`](https://docs.python.org/3/library/typing.html#module-typing) in tests
  ([#5686](https://github.com/scrapy/scrapy/issues/5686), [#5697](https://github.com/scrapy/scrapy/issues/5697)).
- Modernized our CI configuration ([#5695](https://github.com/scrapy/scrapy/issues/5695), [#5696](https://github.com/scrapy/scrapy/issues/5696)).

## Scrapy 2.7.0 (2022-10-17)

Highlights:

- Added Python 3.11 support, dropped Python 3.6 support
- Improved support for [asynchronous callbacks](../topics/coroutines.md)
- [Asyncio support](../topics/asyncio.md) is enabled by default on new
  projects
- Output names of item fields can now be arbitrary strings
- Centralized [request fingerprinting](../topics/request-response.md "Request fingerprints")
  configuration is now possible

### Modified requirements

Python 3.7 or greater is now required; support for Python 3.6 has been dropped.
Support for the upcoming Python 3.11 has been added.

The minimum required version of some dependencies has changed as well:

- [lxml](https://lxml.de/): 3.5.0 → 4.3.0
- [Pillow](https://github.com/python-pillow/Pillow) ([images pipeline](../topics/media-pipeline.md "Using the Images Pipeline")): 4.0.0 → 7.1.0
- [zope.interface](https://zopeinterface.readthedocs.io/en/latest/): 5.0.0 → 5.1.0

([#5512](https://github.com/scrapy/scrapy/issues/5512), [#5514](https://github.com/scrapy/scrapy/issues/5514), [#5524](https://github.com/scrapy/scrapy/issues/5524), [#5563](https://github.com/scrapy/scrapy/issues/5563), [#5664](https://github.com/scrapy/scrapy/issues/5664),
[#5670](https://github.com/scrapy/scrapy/issues/5670), [#5678](https://github.com/scrapy/scrapy/issues/5678))

### Deprecations

- [`ImagesPipeline.thumb_path`](../topics/media-pipeline.md) must now accept an
  `item` parameter ([#5504](https://github.com/scrapy/scrapy/issues/5504), [#5508](https://github.com/scrapy/scrapy/issues/5508)).
- The `scrapy.downloadermiddlewares.decompression` module is now
  deprecated ([#5546](https://github.com/scrapy/scrapy/issues/5546), [#5547](https://github.com/scrapy/scrapy/issues/5547)).

### New features

- The
  [`process_spider_output()`](../topics/spider-middleware.md)
  method of [spider middlewares](../topics/spider-middleware.md) can now be
  defined as an [asynchronous generator](https://docs.python.org/3/glossary.html#term-asynchronous-generator) ([#4978](https://github.com/scrapy/scrapy/issues/4978)).
- The output of [`Request`](../topics/request-response.md) callbacks defined as
  [coroutines](../topics/coroutines.md) is now processed asynchronously
  ([#4978](https://github.com/scrapy/scrapy/issues/4978)).
- [`CrawlSpider`](../topics/spiders.md) now supports [asynchronous
  callbacks](../topics/coroutines.md) ([#5657](https://github.com/scrapy/scrapy/issues/5657)).
- New projects created with the [`startproject`](../topics/commands.md) command have
  [asyncio support](../topics/asyncio.md) enabled by default ([#5590](https://github.com/scrapy/scrapy/issues/5590),
  [#5679](https://github.com/scrapy/scrapy/issues/5679)).
- The [`FEED_EXPORT_FIELDS`](../topics/feed-exports.md) setting can now be defined as a
  dictionary to customize the output name of item fields, lifting the
  restriction that required output names to be valid Python identifiers, e.g.
  preventing them to have whitespace ([#1008](https://github.com/scrapy/scrapy/issues/1008), [#3266](https://github.com/scrapy/scrapy/issues/3266),
  [#3696](https://github.com/scrapy/scrapy/issues/3696)).
- You can now customize [request fingerprinting](../topics/request-response.md "Request fingerprints")
  through the new [`REQUEST_FINGERPRINTER_CLASS`](../topics/request-response.md) setting, instead of
  having to change it on every Scrapy component that relies on request
  fingerprinting ([#900](https://github.com/scrapy/scrapy/issues/900), [#3420](https://github.com/scrapy/scrapy/issues/3420), [#4113](https://github.com/scrapy/scrapy/issues/4113), [#4762](https://github.com/scrapy/scrapy/issues/4762),
  [#4524](https://github.com/scrapy/scrapy/issues/4524)).
- `jsonl` is now supported and encouraged as a file extension for [JSON
  Lines](https://jsonlines.org/) files ([#4848](https://github.com/scrapy/scrapy/issues/4848)).
- [`ImagesPipeline.thumb_path`](../topics/media-pipeline.md) now receives the
  source [item](../topics/items.md) ([#5504](https://github.com/scrapy/scrapy/issues/5504), [#5508](https://github.com/scrapy/scrapy/issues/5508)).

### Bug fixes

- When using Google Cloud Storage with a [media pipeline](../topics/media-pipeline.md), [`FILES_EXPIRES`](../topics/media-pipeline.md) now also works when
  [`FILES_STORE`](../topics/media-pipeline.md) does not point at the root of your Google Cloud
  Storage bucket ([#5317](https://github.com/scrapy/scrapy/issues/5317), [#5318](https://github.com/scrapy/scrapy/issues/5318)).
- The [`parse`](../topics/commands.md) command now supports [asynchronous callbacks](../topics/coroutines.md) ([#5424](https://github.com/scrapy/scrapy/issues/5424), [#5577](https://github.com/scrapy/scrapy/issues/5577)).
- When using the [`parse`](../topics/commands.md) command with a URL for which there is no
  available spider, an exception is no longer raised ([#3264](https://github.com/scrapy/scrapy/issues/3264),
  [#3265](https://github.com/scrapy/scrapy/issues/3265), [#5375](https://github.com/scrapy/scrapy/issues/5375), [#5376](https://github.com/scrapy/scrapy/issues/5376), [#5497](https://github.com/scrapy/scrapy/issues/5497)).
- [`TextResponse`](../topics/request-response.md) now gives higher priority to the [byte
  order mark](https://en.wikipedia.org/wiki/Byte_order_mark) when determining the text encoding of the response body,
  following the [HTML living standard](https://html.spec.whatwg.org/multipage/parsing.html#determining-the-character-encoding) ([#5601](https://github.com/scrapy/scrapy/issues/5601), [#5611](https://github.com/scrapy/scrapy/issues/5611)).
- MIME sniffing takes the response body into account in FTP and HTTP/1.0
  requests, as well as in cached requests ([#4873](https://github.com/scrapy/scrapy/issues/4873)).
- MIME sniffing now detects valid HTML 5 documents even if the `html` tag
  is missing ([#4873](https://github.com/scrapy/scrapy/issues/4873)).
- An exception is now raised if [`ASYNCIO_EVENT_LOOP`](../topics/settings.md) has a value
  that does not match the asyncio event loop actually installed
  ([#5529](https://github.com/scrapy/scrapy/issues/5529)).
- Fixed `Headers.getlist()`
  returning only the last header ([#5515](https://github.com/scrapy/scrapy/issues/5515), [#5526](https://github.com/scrapy/scrapy/issues/5526)).
- Fixed [`LinkExtractor`](../topics/link-extractors.md) not ignoring the
  `tar.gz` file extension by default ([#1837](https://github.com/scrapy/scrapy/issues/1837), [#2067](https://github.com/scrapy/scrapy/issues/2067),
  [#4066](https://github.com/scrapy/scrapy/issues/4066))

### Documentation

- Clarified the return type of [`Spider.parse`](../topics/spiders.md)
  ([#5602](https://github.com/scrapy/scrapy/issues/5602), [#5608](https://github.com/scrapy/scrapy/issues/5608)).
- To enable
  [`HttpCompressionMiddleware`](../topics/downloader-middleware.md)
  to do [brotli compression](https://www.ietf.org/rfc/rfc7932.txt), installing [brotli](https://github.com/google/brotli) is now recommended instead
  of installing [brotlipy](https://github.com/python-hyper/brotlipy/), as the former provides a more recent version of
  brotli.
- [Signal documentation](../topics/signals.md) now mentions [coroutine
  support](../topics/coroutines.md) and uses it in code examples ([#4852](https://github.com/scrapy/scrapy/issues/4852),
  [#5358](https://github.com/scrapy/scrapy/issues/5358)).
- [Avoiding getting banned](../topics/practices.md) now recommends [Common Crawl](https://commoncrawl.org/) instead of [Google cache](https://www.googleguide.com/cached_pages.html)
  ([#3582](https://github.com/scrapy/scrapy/issues/3582), [#5432](https://github.com/scrapy/scrapy/issues/5432)).
- The new [Components](../topics/components.md) topic covers enforcing requirements on
  Scrapy components, like [downloader middlewares](../topics/downloader-middleware.md), [extensions](../topics/extensions.md),
  [item pipelines](../topics/item-pipeline.md), [spider middlewares](../topics/spider-middleware.md), and more; [Enforcing asyncio as a requirement](../topics/asyncio.md)
  has also been added ([#4978](https://github.com/scrapy/scrapy/issues/4978)).
- [Settings](../topics/settings.md) now indicates that setting values must be
  [picklable](https://docs.python.org/3/library/pickle.html#pickle-picklable) ([#5607](https://github.com/scrapy/scrapy/issues/5607), [#5629](https://github.com/scrapy/scrapy/issues/5629)).
- Removed outdated documentation ([#5446](https://github.com/scrapy/scrapy/issues/5446), [#5373](https://github.com/scrapy/scrapy/issues/5373),
  [#5369](https://github.com/scrapy/scrapy/issues/5369), [#5370](https://github.com/scrapy/scrapy/issues/5370), [#5554](https://github.com/scrapy/scrapy/issues/5554)).
- Fixed typos ([#5442](https://github.com/scrapy/scrapy/issues/5442), [#5455](https://github.com/scrapy/scrapy/issues/5455), [#5457](https://github.com/scrapy/scrapy/issues/5457), [#5461](https://github.com/scrapy/scrapy/issues/5461),
  [#5538](https://github.com/scrapy/scrapy/issues/5538), [#5553](https://github.com/scrapy/scrapy/issues/5553), [#5558](https://github.com/scrapy/scrapy/issues/5558), [#5624](https://github.com/scrapy/scrapy/issues/5624), [#5631](https://github.com/scrapy/scrapy/issues/5631)).
- Fixed other issues ([#5283](https://github.com/scrapy/scrapy/issues/5283), [#5284](https://github.com/scrapy/scrapy/issues/5284), [#5559](https://github.com/scrapy/scrapy/issues/5559),
  [#5567](https://github.com/scrapy/scrapy/issues/5567), [#5648](https://github.com/scrapy/scrapy/issues/5648), [#5659](https://github.com/scrapy/scrapy/issues/5659), [#5665](https://github.com/scrapy/scrapy/issues/5665)).

### Quality assurance

- Added a continuous integration job to run [twine check](https://twine.readthedocs.io/en/stable/#twine-check) ([#5655](https://github.com/scrapy/scrapy/issues/5655),
  [#5656](https://github.com/scrapy/scrapy/issues/5656)).
- Addressed test issues and warnings ([#5560](https://github.com/scrapy/scrapy/issues/5560), [#5561](https://github.com/scrapy/scrapy/issues/5561),
  [#5612](https://github.com/scrapy/scrapy/issues/5612), [#5617](https://github.com/scrapy/scrapy/issues/5617), [#5639](https://github.com/scrapy/scrapy/issues/5639), [#5645](https://github.com/scrapy/scrapy/issues/5645), [#5662](https://github.com/scrapy/scrapy/issues/5662),
  [#5671](https://github.com/scrapy/scrapy/issues/5671), [#5675](https://github.com/scrapy/scrapy/issues/5675)).
- Cleaned up code ([#4991](https://github.com/scrapy/scrapy/issues/4991), [#4995](https://github.com/scrapy/scrapy/issues/4995), [#5451](https://github.com/scrapy/scrapy/issues/5451),
  [#5487](https://github.com/scrapy/scrapy/issues/5487), [#5542](https://github.com/scrapy/scrapy/issues/5542), [#5667](https://github.com/scrapy/scrapy/issues/5667), [#5668](https://github.com/scrapy/scrapy/issues/5668), [#5672](https://github.com/scrapy/scrapy/issues/5672)).
- Applied minor code improvements ([#5661](https://github.com/scrapy/scrapy/issues/5661)).

## Scrapy 2.6.3 (2022-09-27)

- Added support for [pyOpenSSL](https://www.pyopenssl.org/en/stable/) 22.1.0, removing support for SSLv3
  ([#5634](https://github.com/scrapy/scrapy/issues/5634), [#5635](https://github.com/scrapy/scrapy/issues/5635), [#5636](https://github.com/scrapy/scrapy/issues/5636)).
- Upgraded the minimum versions of the following dependencies:
  - [cryptography](https://cryptography.io/en/latest/): 2.0 → 3.3
  - [pyOpenSSL](https://www.pyopenssl.org/en/stable/): 16.2.0 → 21.0.0
  - [service_identity](https://service-identity.readthedocs.io/en/stable/): 16.0.0 → 18.1.0
  - [Twisted](https://twisted.org/): 17.9.0 → 18.9.0
  - [zope.interface](https://zopeinterface.readthedocs.io/en/latest/): 4.1.3 → 5.0.0

  ([#5621](https://github.com/scrapy/scrapy/issues/5621), [#5632](https://github.com/scrapy/scrapy/issues/5632))
- Fixes test and documentation issues ([#5612](https://github.com/scrapy/scrapy/issues/5612), [#5617](https://github.com/scrapy/scrapy/issues/5617),
  [#5631](https://github.com/scrapy/scrapy/issues/5631)).

## Scrapy 2.6.2 (2022-07-25)

**Security bug fix:**

- When [`HttpProxyMiddleware`](../topics/downloader-middleware.md)
  processes a request with [`proxy`](../topics/downloader-middleware.md) metadata, and that
  [`proxy`](../topics/downloader-middleware.md) metadata includes proxy credentials,
  [`HttpProxyMiddleware`](../topics/downloader-middleware.md) sets
  the `Proxy-Authorization` header, but only if that header is not already
  set.

  There are third-party proxy-rotation downloader middlewares that set
  different [`proxy`](../topics/downloader-middleware.md) metadata every time they process a request.

  Because of request retries and redirects, the same request can be processed
  by downloader middlewares more than once, including both
  [`HttpProxyMiddleware`](../topics/downloader-middleware.md) and
  any third-party proxy-rotation downloader middleware.

  These third-party proxy-rotation downloader middlewares could change the
  [`proxy`](../topics/downloader-middleware.md) metadata of a request to a new value, but fail to remove
  the `Proxy-Authorization` header from the previous value of the
  [`proxy`](../topics/downloader-middleware.md) metadata, causing the credentials of one proxy to be sent
  to a different proxy.

  To prevent the unintended leaking of proxy credentials, the behavior of
  [`HttpProxyMiddleware`](../topics/downloader-middleware.md) is now
  as follows when processing a request:
  - If the request being processed defines [`proxy`](../topics/downloader-middleware.md) metadata that
    includes credentials, the `Proxy-Authorization` header is always
    updated to feature those credentials.
  - If the request being processed defines [`proxy`](../topics/downloader-middleware.md) metadata
    without credentials, the `Proxy-Authorization` header is removed
    *unless* it was originally defined for the same proxy URL.

    To remove proxy credentials while keeping the same proxy URL, remove
    the `Proxy-Authorization` header.
  - If the request has no [`proxy`](../topics/downloader-middleware.md) metadata, or that metadata is a
    falsy value (e.g. `None`), the `Proxy-Authorization` header is
    removed.

    It is no longer possible to set a proxy URL through the
    [`proxy`](../topics/downloader-middleware.md) metadata but set the credentials through the
    `Proxy-Authorization` header. Set proxy credentials through the
    [`proxy`](../topics/downloader-middleware.md) metadata instead.

Also fixes the following regressions introduced in 2.6.0:

- [`CrawlerProcess`](../topics/api.md) supports again crawling multiple
  spiders ([#5435](https://github.com/scrapy/scrapy/issues/5435), [#5436](https://github.com/scrapy/scrapy/issues/5436))
- Installing a Twisted reactor before Scrapy does (e.g. importing
  [`twisted.internet.reactor`](https://docs.twisted.org/en/stable/api/twisted.internet.reactor.html) somewhere at the module level) no longer
  prevents Scrapy from starting, as long as a different reactor is not
  specified in `TWISTED_REACTOR` ([#5525](https://github.com/scrapy/scrapy/issues/5525), [#5528](https://github.com/scrapy/scrapy/issues/5528))
- Fixed an exception that was being logged after the spider finished under
  certain conditions ([#5437](https://github.com/scrapy/scrapy/issues/5437), [#5440](https://github.com/scrapy/scrapy/issues/5440))
- The `--output`/`-o` command-line parameter supports again a value
  starting with a hyphen ([#5444](https://github.com/scrapy/scrapy/issues/5444), [#5445](https://github.com/scrapy/scrapy/issues/5445))
- The `scrapy parse -h` command no longer throws an error ([#5481](https://github.com/scrapy/scrapy/issues/5481),
  [#5482](https://github.com/scrapy/scrapy/issues/5482))

## Scrapy 2.6.1 (2022-03-01)

Fixes a regression introduced in 2.6.0 that would unset the request method when
following redirects.

## Scrapy 2.6.0 (2022-03-01)

Highlights:

* Security fixes for cookie handling (see Security bug fixes)
* Python 3.10 support
* [asyncio support](../topics/asyncio.md) is no longer considered
  experimental, and works out-of-the-box on Windows regardless of your Python
  version
* Feed exports now support [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) output paths and per-feed
  [item filtering](../topics/feed-exports.md) and
  [post-processing](../topics/feed-exports.md)

### Security bug fixes

- When a [`Request`](../topics/request-response.md) object with cookies defined gets a
  redirect response causing a new [`Request`](../topics/request-response.md) object to be
  scheduled, the cookies defined in the original
  [`Request`](../topics/request-response.md) object are no longer copied into the new
  [`Request`](../topics/request-response.md) object.

  If you manually set the `Cookie` header on a
  [`Request`](../topics/request-response.md) object and the domain name of the redirect
  URL is not an exact match for the domain of the URL of the original
  [`Request`](../topics/request-response.md) object, your `Cookie` header is now dropped
  from the new [`Request`](../topics/request-response.md) object.

  The old behavior could be exploited by an attacker to gain access to your
  cookies. Please, see the [cjvr-mfj7-j4j8 security advisory](https://github.com/scrapy/scrapy/security/advisories/GHSA-cjvr-mfj7-j4j8) for more
  information.
  > [!NOTE]
  > It is still possible to enable the sharing of cookies between
  > different domains with a shared domain suffix (e.g.
  > `example.com` and any subdomain) by defining the shared domain
  > suffix (e.g. `example.com`) as the cookie domain when defining
  > your cookies. See the documentation of the
  > [`Request`](../topics/request-response.md) class for more information.
- When the domain of a cookie, either received in the `Set-Cookie` header
  of a response or defined in a [`Request`](../topics/request-response.md) object, is set
  to a [public suffix](https://publicsuffix.org/), the cookie is now
  ignored unless the cookie domain is the same as the request domain.

  The old behavior could be exploited by an attacker to inject cookies from a
  controlled domain into your cookiejar that could be sent to other domains
  not controlled by the attacker. Please, see the [mfjm-vh54-3f96 security
  advisory](https://github.com/scrapy/scrapy/security/advisories/GHSA-mfjm-vh54-3f96) for more information.

### Modified requirements

- The [h2](https://pypi.org/project/h2/) dependency is now optional, only needed to
  [enable HTTP/2 support](../topics/download-handlers.md "H2DownloadHandler"). ([#5113](https://github.com/scrapy/scrapy/issues/5113))

### Backward-incompatible changes

- The `formdata` parameter of [`FormRequest`](../topics/request-response.md), if specified
  for a non-POST request, now overrides the URL query string, instead of
  being appended to it. ([#2919](https://github.com/scrapy/scrapy/issues/2919), [#3579](https://github.com/scrapy/scrapy/issues/3579))
- When a function is assigned to the [`FEED_URI_PARAMS`](../topics/feed-exports.md) setting, now
  the return value of that function, and not the `params` input parameter,
  will determine the feed URI parameters, unless that return value is
  `None`. ([#4962](https://github.com/scrapy/scrapy/issues/4962), [#4966](https://github.com/scrapy/scrapy/issues/4966))
- In [`scrapy.core.engine.ExecutionEngine`](../topics/api.md), methods
  `crawl()`,
  `download()`,
  `schedule()`,
  and `spider_is_idle()`
  now raise `RuntimeError` if called before
  `open_spider()`. ([#5090](https://github.com/scrapy/scrapy/issues/5090))

  These methods used to assume that
  `ExecutionEngine.slot` had
  been defined by a prior call to
  `open_spider()`, so they were
  raising `AttributeError` instead.
- If the API of the configured [scheduler](../topics/scheduler.md) does not
  meet expectations, `TypeError` is now raised at startup time. Before,
  other exceptions would be raised at run time. ([#3559](https://github.com/scrapy/scrapy/issues/3559))
- The `_encoding` field of serialized [`Request`](../topics/request-response.md) objects
  is now named `encoding`, in line with all other fields ([#5130](https://github.com/scrapy/scrapy/issues/5130))

### Deprecation removals

- `scrapy.http.TextResponse.body_as_unicode`, deprecated in Scrapy 2.2, has
  now been removed. ([#5393](https://github.com/scrapy/scrapy/issues/5393))
- `scrapy.item.BaseItem`, deprecated in Scrapy 2.2, has now been removed.
  ([#5398](https://github.com/scrapy/scrapy/issues/5398))
- `scrapy.item.DictItem`, deprecated in Scrapy 1.8, has now been removed.
  ([#5398](https://github.com/scrapy/scrapy/issues/5398))
- `scrapy.Spider.make_requests_from_url`, deprecated in Scrapy 1.4, has now
  been removed. ([#4178](https://github.com/scrapy/scrapy/issues/4178), [#4356](https://github.com/scrapy/scrapy/issues/4356))

### Deprecations

- When a function is assigned to the [`FEED_URI_PARAMS`](../topics/feed-exports.md) setting,
  returning `None` or modifying the `params` input parameter is now
  deprecated. Return a new dictionary instead. ([#4962](https://github.com/scrapy/scrapy/issues/4962), [#4966](https://github.com/scrapy/scrapy/issues/4966))
- `scrapy.utils.reqser` is deprecated. ([#5130](https://github.com/scrapy/scrapy/issues/5130))
  - Instead of `request_to_dict()`, use the new
    [`Request.to_dict()`](../topics/request-response.md) method.
  - Instead of `request_from_dict()`, use the new
    [`scrapy.utils.request.request_from_dict()`](../topics/request-response.md) function.
- In `scrapy.squeues`, the following queue classes are deprecated:
  `PickleFifoDiskQueueNonRequest`,
  `PickleLifoDiskQueueNonRequest`,
  `MarshalFifoDiskQueueNonRequest`,
  and `MarshalLifoDiskQueueNonRequest`. You should
  instead use:
  `PickleFifoDiskQueue`,
  `PickleLifoDiskQueue`,
  `MarshalFifoDiskQueue`,
  and `MarshalLifoDiskQueue`. ([#5117](https://github.com/scrapy/scrapy/issues/5117))
- Many aspects of [`scrapy.core.engine.ExecutionEngine`](../topics/api.md) that come from
  a time when this class could handle multiple [`Spider`](../topics/spiders.md)
  objects at a time have been deprecated. ([#5090](https://github.com/scrapy/scrapy/issues/5090))
  - The `has_capacity()` method
    is deprecated.
  - The `schedule()` method is
    deprecated, use `crawl()` or
    `download()` instead.
  - The `open_spiders` attribute
    is deprecated, use `spider`
    instead.
  - The `spider` parameter is deprecated for the following methods:
    - `spider_is_idle()`
    - `crawl()`
    - `download()`

    Instead, call `open_spider()`
    first to set the [`Spider`](../topics/spiders.md) object.
- `scrapy.utils.response.response_httprepr()` is now deprecated.
  ([#4972](https://github.com/scrapy/scrapy/issues/4972))

### New features

- You can now use [item filtering](../topics/feed-exports.md) to control which items
  are exported to each output feed. ([#4575](https://github.com/scrapy/scrapy/issues/4575), [#5178](https://github.com/scrapy/scrapy/issues/5178),
  [#5161](https://github.com/scrapy/scrapy/issues/5161), [#5203](https://github.com/scrapy/scrapy/issues/5203))
- You can now apply [post-processing](../topics/feed-exports.md) to feeds, and
  [built-in post-processing plugins](../topics/feed-exports.md "Built-in Plugins") are provided for
  output file compression. ([#2174](https://github.com/scrapy/scrapy/issues/2174), [#5168](https://github.com/scrapy/scrapy/issues/5168), [#5190](https://github.com/scrapy/scrapy/issues/5190))
- The [`FEEDS`](../topics/feed-exports.md) setting now supports [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) objects as
  keys. ([#5383](https://github.com/scrapy/scrapy/issues/5383), [#5384](https://github.com/scrapy/scrapy/issues/5384))
- Enabling [asyncio](../topics/asyncio.md) while using Windows and Python 3.8
  or later will automatically switch the asyncio event loop to one that
  allows Scrapy to work. See [Windows-specific notes](../topics/asyncio.md). ([#4976](https://github.com/scrapy/scrapy/issues/4976),
  [#5315](https://github.com/scrapy/scrapy/issues/5315))
- The [`genspider`](../topics/commands.md) command now supports a start URL instead of a
  domain name. ([#4439](https://github.com/scrapy/scrapy/issues/4439))
- `scrapy.utils.defer` gained 2 new functions,
  [`deferred_to_future()`](../topics/asyncio.md) and
  [`maybe_deferred_to_future()`](../topics/asyncio.md), to help [await
  on Deferreds when using the asyncio reactor](../topics/asyncio.md "Integrating Deferred code and asyncio code").
  ([#5288](https://github.com/scrapy/scrapy/issues/5288))
- [Amazon S3 feed export storage](../topics/feed-exports.md "S3") gained
  support for [temporary security credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html)
  ([`AWS_SESSION_TOKEN`](../topics/settings.md)) and endpoint customization
  ([`AWS_ENDPOINT_URL`](../topics/settings.md)). ([#4998](https://github.com/scrapy/scrapy/issues/4998), [#5210](https://github.com/scrapy/scrapy/issues/5210))
- New [`LOG_FILE_APPEND`](../topics/settings.md) setting to allow truncating the log file.
  ([#5279](https://github.com/scrapy/scrapy/issues/5279))
- `Request.cookies` values that are
  `bool`, `float` or `int` are cast to `str`.
  ([#5252](https://github.com/scrapy/scrapy/issues/5252), [#5253](https://github.com/scrapy/scrapy/issues/5253))
- You may now raise [`CloseSpider`](../topics/exceptions.md) from a handler of
  the [`spider_idle`](../topics/signals.md) signal to customize the reason why the spider is
  stopping. ([#5191](https://github.com/scrapy/scrapy/issues/5191))
- When using
  [`HttpProxyMiddleware`](../topics/downloader-middleware.md), the
  proxy URL for non-HTTPS HTTP/1.1 requests no longer needs to include a URL
  scheme. ([#4505](https://github.com/scrapy/scrapy/issues/4505), [#4649](https://github.com/scrapy/scrapy/issues/4649))
- All built-in queues now expose a `peek` method that returns the next
  queue object (like `pop`) but does not remove the returned object from
  the queue. ([#5112](https://github.com/scrapy/scrapy/issues/5112))

  If the underlying queue does not support peeking (e.g. because you are not
  using `queuelib` 1.6.1 or later), the `peek` method raises
  `NotImplementedError`.
- [`Request`](../topics/request-response.md) and [`Response`](../topics/request-response.md) now have
  an `attributes` attribute that makes subclassing easier. For
  [`Request`](../topics/request-response.md), it also allows subclasses to work with
  [`scrapy.utils.request.request_from_dict()`](../topics/request-response.md). ([#1877](https://github.com/scrapy/scrapy/issues/1877),
  [#5130](https://github.com/scrapy/scrapy/issues/5130), [#5218](https://github.com/scrapy/scrapy/issues/5218))
- The [`open()`](../topics/scheduler.md) and
  [`close()`](../topics/scheduler.md) methods of the
  [scheduler](../topics/scheduler.md) are now optional. ([#3559](https://github.com/scrapy/scrapy/issues/3559))
- HTTP/1.1 `TunnelError`
  exceptions now only truncate response bodies longer than 1000 characters,
  instead of those longer than 32 characters, making it easier to debug such
  errors. ([#4881](https://github.com/scrapy/scrapy/issues/4881), [#5007](https://github.com/scrapy/scrapy/issues/5007))
- [`ItemLoader`](../topics/loaders.md) now supports non-text responses.
  ([#5145](https://github.com/scrapy/scrapy/issues/5145), [#5269](https://github.com/scrapy/scrapy/issues/5269))

### Bug fixes

- The `TWISTED_REACTOR` and [`ASYNCIO_EVENT_LOOP`](../topics/settings.md) settings
  are no longer ignored if defined in [`custom_settings`](../topics/spiders.md).
  ([#4485](https://github.com/scrapy/scrapy/issues/4485), [#5352](https://github.com/scrapy/scrapy/issues/5352))
- Removed a module-level Twisted reactor import that could prevent
  [using the asyncio reactor](../topics/asyncio.md). ([#5357](https://github.com/scrapy/scrapy/issues/5357))
- The [`startproject`](../topics/commands.md) command works with existing folders again.
  ([#4665](https://github.com/scrapy/scrapy/issues/4665), [#4676](https://github.com/scrapy/scrapy/issues/4676))
- The [`FEED_URI_PARAMS`](../topics/feed-exports.md) setting now behaves as documented.
  ([#4962](https://github.com/scrapy/scrapy/issues/4962), [#4966](https://github.com/scrapy/scrapy/issues/4966))
- [`Request.cb_kwargs`](../topics/request-response.md) once again allows the
  `callback` keyword. ([#5237](https://github.com/scrapy/scrapy/issues/5237), [#5251](https://github.com/scrapy/scrapy/issues/5251), [#5264](https://github.com/scrapy/scrapy/issues/5264))
- Made [`scrapy.utils.response.open_in_browser()`](../topics/debug.md) support more complex
  HTML. ([#5319](https://github.com/scrapy/scrapy/issues/5319), [#5320](https://github.com/scrapy/scrapy/issues/5320))
- Fixed [`CSVFeedSpider.quotechar`](../topics/spiders.md) being interpreted as the CSV file
  encoding. ([#5391](https://github.com/scrapy/scrapy/issues/5391), [#5394](https://github.com/scrapy/scrapy/issues/5394))
- Added missing [setuptools](https://pypi.org/project/setuptools/) to the list of dependencies. ([#5122](https://github.com/scrapy/scrapy/issues/5122))
- [`LinkExtractor`](../topics/link-extractors.md)
  now also works as expected with links that have comma-separated `rel`
  attribute values including `nofollow`. ([#5225](https://github.com/scrapy/scrapy/issues/5225))
- Fixed a `TypeError` that could be raised during [feed export](../topics/feed-exports.md) parameter parsing. ([#5359](https://github.com/scrapy/scrapy/issues/5359))

### Documentation

- [asyncio support](../topics/asyncio.md) is no longer considered
  experimental. ([#5332](https://github.com/scrapy/scrapy/issues/5332))
- Included [Windows-specific help for asyncio usage](../topics/asyncio.md "Windows-specific notes").
  ([#4976](https://github.com/scrapy/scrapy/issues/4976), [#5315](https://github.com/scrapy/scrapy/issues/5315))
- Rewrote [Using a headless browser](../topics/dynamic-content.md) with up-to-date best practices.
  ([#4484](https://github.com/scrapy/scrapy/issues/4484), [#4613](https://github.com/scrapy/scrapy/issues/4613))
- Documented [local file naming in media pipelines](../topics/media-pipeline.md "File Naming"). ([#5069](https://github.com/scrapy/scrapy/issues/5069), [#5152](https://github.com/scrapy/scrapy/issues/5152))
- [Frequently Asked Questions](../faq.md) now covers spider file name collision issues. ([#2680](https://github.com/scrapy/scrapy/issues/2680),
  [#3669](https://github.com/scrapy/scrapy/issues/3669))
- Provided better context and instructions to disable the
  [`URLLENGTH_LIMIT`](../topics/settings.md) setting. ([#5135](https://github.com/scrapy/scrapy/issues/5135), [#5250](https://github.com/scrapy/scrapy/issues/5250))
- Documented that Reppy parser does not support Python 3.9+.
  ([#5226](https://github.com/scrapy/scrapy/issues/5226), [#5231](https://github.com/scrapy/scrapy/issues/5231))
- Documented [the scheduler component](../topics/scheduler.md).
  ([#3537](https://github.com/scrapy/scrapy/issues/3537), [#3559](https://github.com/scrapy/scrapy/issues/3559))
- Documented the method used by [media pipelines](../topics/media-pipeline.md) to [determine if a file has expired](../topics/media-pipeline.md "File expiration"). ([#5120](https://github.com/scrapy/scrapy/issues/5120), [#5254](https://github.com/scrapy/scrapy/issues/5254))
- [Running multiple spiders in the same process](../topics/practices.md) now features
  [`scrapy.utils.project.get_project_settings()`](../topics/api.md) usage. ([#5070](https://github.com/scrapy/scrapy/issues/5070))
- [Running multiple spiders in the same process](../topics/practices.md) now covers what happens when you define
  different per-spider values for some settings that cannot differ at run
  time. ([#4485](https://github.com/scrapy/scrapy/issues/4485), [#5352](https://github.com/scrapy/scrapy/issues/5352))
- Extended the documentation of the
  `StatsMailer` extension.
  ([#5199](https://github.com/scrapy/scrapy/issues/5199), [#5217](https://github.com/scrapy/scrapy/issues/5217))
- Added [`JOBDIR`](../topics/settings.md) to [Settings](../topics/settings.md). ([#5173](https://github.com/scrapy/scrapy/issues/5173),
  [#5224](https://github.com/scrapy/scrapy/issues/5224))
- Documented `Spider.attribute`.
  ([#5174](https://github.com/scrapy/scrapy/issues/5174), [#5244](https://github.com/scrapy/scrapy/issues/5244))
- Documented [`TextResponse.urljoin`](../topics/request-response.md).
  ([#1582](https://github.com/scrapy/scrapy/issues/1582))
- Added the `body_length` parameter to the documented signature of the
  [`headers_received`](../topics/signals.md) signal. ([#5270](https://github.com/scrapy/scrapy/issues/5270))
- Clarified [`SelectorList.get`](../topics/selectors.md) usage
  in the [tutorial](../intro/tutorial.md). ([#5256](https://github.com/scrapy/scrapy/issues/5256))
- The documentation now features the shortest import path of classes with
  multiple import paths. ([#2733](https://github.com/scrapy/scrapy/issues/2733), [#5099](https://github.com/scrapy/scrapy/issues/5099))
- `quotes.toscrape.com` references now use HTTPS instead of HTTP.
  ([#5395](https://github.com/scrapy/scrapy/issues/5395), [#5396](https://github.com/scrapy/scrapy/issues/5396))
- Added a link to [our Discord server](https://discord.com/invite/mv3yErfpvq)
  to [Getting help](../intro/getting-help.md). ([#5421](https://github.com/scrapy/scrapy/issues/5421), [#5422](https://github.com/scrapy/scrapy/issues/5422))
- The pronunciation of the project name is now [officially](../intro/overview.md) /ˈskreɪpaɪ/. ([#5280](https://github.com/scrapy/scrapy/issues/5280), [#5281](https://github.com/scrapy/scrapy/issues/5281))
- Added the Scrapy logo to the README. ([#5255](https://github.com/scrapy/scrapy/issues/5255), [#5258](https://github.com/scrapy/scrapy/issues/5258))
- Fixed issues and implemented minor improvements. ([#3155](https://github.com/scrapy/scrapy/issues/3155),
  [#4335](https://github.com/scrapy/scrapy/issues/4335), [#5074](https://github.com/scrapy/scrapy/issues/5074), [#5098](https://github.com/scrapy/scrapy/issues/5098), [#5134](https://github.com/scrapy/scrapy/issues/5134), [#5180](https://github.com/scrapy/scrapy/issues/5180),
  [#5194](https://github.com/scrapy/scrapy/issues/5194), [#5239](https://github.com/scrapy/scrapy/issues/5239), [#5266](https://github.com/scrapy/scrapy/issues/5266), [#5271](https://github.com/scrapy/scrapy/issues/5271), [#5273](https://github.com/scrapy/scrapy/issues/5273),
  [#5274](https://github.com/scrapy/scrapy/issues/5274), [#5276](https://github.com/scrapy/scrapy/issues/5276), [#5347](https://github.com/scrapy/scrapy/issues/5347), [#5356](https://github.com/scrapy/scrapy/issues/5356), [#5414](https://github.com/scrapy/scrapy/issues/5414),
  [#5415](https://github.com/scrapy/scrapy/issues/5415), [#5416](https://github.com/scrapy/scrapy/issues/5416), [#5419](https://github.com/scrapy/scrapy/issues/5419), [#5420](https://github.com/scrapy/scrapy/issues/5420))

### Quality Assurance

- Added support for Python 3.10. ([#5212](https://github.com/scrapy/scrapy/issues/5212), [#5221](https://github.com/scrapy/scrapy/issues/5221),
  [#5265](https://github.com/scrapy/scrapy/issues/5265))
- Significantly reduced memory usage by
  `scrapy.utils.response.response_httprepr()`, used by the
  [`DownloaderStats`](../topics/downloader-middleware.md) downloader
  middleware, which is enabled by default. ([#4964](https://github.com/scrapy/scrapy/issues/4964), [#4972](https://github.com/scrapy/scrapy/issues/4972))
- Removed uses of the deprecated [`optparse`](https://docs.python.org/3/library/optparse.html#module-optparse) module. ([#5366](https://github.com/scrapy/scrapy/issues/5366),
  [#5374](https://github.com/scrapy/scrapy/issues/5374))
- Extended typing hints. ([#5077](https://github.com/scrapy/scrapy/issues/5077), [#5090](https://github.com/scrapy/scrapy/issues/5090), [#5100](https://github.com/scrapy/scrapy/issues/5100),
  [#5108](https://github.com/scrapy/scrapy/issues/5108), [#5171](https://github.com/scrapy/scrapy/issues/5171), [#5215](https://github.com/scrapy/scrapy/issues/5215), [#5334](https://github.com/scrapy/scrapy/issues/5334))
- Improved tests, fixed CI issues, removed unused code. ([#5094](https://github.com/scrapy/scrapy/issues/5094),
  [#5157](https://github.com/scrapy/scrapy/issues/5157), [#5162](https://github.com/scrapy/scrapy/issues/5162), [#5198](https://github.com/scrapy/scrapy/issues/5198), [#5207](https://github.com/scrapy/scrapy/issues/5207), [#5208](https://github.com/scrapy/scrapy/issues/5208),
  [#5229](https://github.com/scrapy/scrapy/issues/5229), [#5298](https://github.com/scrapy/scrapy/issues/5298), [#5299](https://github.com/scrapy/scrapy/issues/5299), [#5310](https://github.com/scrapy/scrapy/issues/5310), [#5316](https://github.com/scrapy/scrapy/issues/5316),
  [#5333](https://github.com/scrapy/scrapy/issues/5333), [#5388](https://github.com/scrapy/scrapy/issues/5388), [#5389](https://github.com/scrapy/scrapy/issues/5389), [#5400](https://github.com/scrapy/scrapy/issues/5400), [#5401](https://github.com/scrapy/scrapy/issues/5401),
  [#5404](https://github.com/scrapy/scrapy/issues/5404), [#5405](https://github.com/scrapy/scrapy/issues/5405), [#5407](https://github.com/scrapy/scrapy/issues/5407), [#5410](https://github.com/scrapy/scrapy/issues/5410), [#5412](https://github.com/scrapy/scrapy/issues/5412),
  [#5425](https://github.com/scrapy/scrapy/issues/5425), [#5427](https://github.com/scrapy/scrapy/issues/5427))
- Implemented improvements for contributors. ([#5080](https://github.com/scrapy/scrapy/issues/5080), [#5082](https://github.com/scrapy/scrapy/issues/5082),
  [#5177](https://github.com/scrapy/scrapy/issues/5177), [#5200](https://github.com/scrapy/scrapy/issues/5200))
- Implemented cleanups. ([#5095](https://github.com/scrapy/scrapy/issues/5095), [#5106](https://github.com/scrapy/scrapy/issues/5106), [#5209](https://github.com/scrapy/scrapy/issues/5209),
  [#5228](https://github.com/scrapy/scrapy/issues/5228), [#5235](https://github.com/scrapy/scrapy/issues/5235), [#5245](https://github.com/scrapy/scrapy/issues/5245), [#5246](https://github.com/scrapy/scrapy/issues/5246), [#5292](https://github.com/scrapy/scrapy/issues/5292),
  [#5314](https://github.com/scrapy/scrapy/issues/5314), [#5322](https://github.com/scrapy/scrapy/issues/5322))

## Scrapy 2.5.1 (2021-10-05)

* **Security bug fix:**

  If you use
  [`HttpAuthMiddleware`](../topics/downloader-middleware.md)
  (i.e. the `http_user` and `http_pass` spider attributes) for HTTP
  authentication, any request exposes your credentials to the request target.

  To prevent unintended exposure of authentication credentials to unintended
  domains, you must now additionally set a new, additional spider attribute,
  `http_auth_domain`, and point it to the specific domain to which the
  authentication credentials must be sent.

  If the `http_auth_domain` spider attribute is not set, the domain of the
  first request will be considered the HTTP authentication target, and
  authentication credentials will only be sent in requests targeting that
  domain.

  If you need to send the same HTTP authentication credentials to multiple
  domains, you can use [`w3lib.http.basic_auth_header()`](https://w3lib.readthedocs.io/en/latest/w3lib.html#w3lib.http.basic_auth_header) instead to
  set the value of the `Authorization` header of your requests.

  If you *really* want your spider to send the same HTTP authentication
  credentials to any domain, set the `http_auth_domain` spider attribute
  to `None`.

  Finally, if you are a user of [scrapy-splash](https://github.com/scrapy-plugins/scrapy-splash), know that this version of
  Scrapy breaks compatibility with scrapy-splash 0.7.2 and earlier. You will
  need to upgrade scrapy-splash to a greater version for it to continue to
  work.

## Scrapy 2.5.0 (2021-04-06)

Highlights:

- Official Python 3.9 support
- Experimental [HTTP/2 support](../topics/download-handlers.md "H2DownloadHandler")
- New [`get_retry_request()`](../topics/downloader-middleware.md) function
  to retry requests from spider callbacks
- New [`headers_received`](../topics/signals.md) signal that allows stopping
  downloads early
- New [`Response.protocol`](../topics/request-response.md) attribute

### Deprecation removals

- Removed all code that [was deprecated in 1.7.0](1.x.md "Deprecations") and
  had not already been removed in 2.4.0 (see Deprecation removals).
  ([#4901](https://github.com/scrapy/scrapy/issues/4901))
- Removed support for the `SCRAPY_PICKLED_SETTINGS_TO_OVERRIDE` environment
  variable, [deprecated in 1.8.0](1.x.md "Deprecations"). ([#4912](https://github.com/scrapy/scrapy/issues/4912))

### Deprecations

- The `scrapy.utils.py36` module is now deprecated in favor of
  `scrapy.utils.asyncgen`. ([#4900](https://github.com/scrapy/scrapy/issues/4900))

### New features

- Experimental [HTTP/2 support](../topics/download-handlers.md "H2DownloadHandler") through a new download handler
  that can be assigned to the `https` protocol in the
  [`DOWNLOAD_HANDLERS`](../topics/settings.md) setting.
  ([#1854](https://github.com/scrapy/scrapy/issues/1854), [#4769](https://github.com/scrapy/scrapy/issues/4769), [#5058](https://github.com/scrapy/scrapy/issues/5058), [#5059](https://github.com/scrapy/scrapy/issues/5059), [#5066](https://github.com/scrapy/scrapy/issues/5066))
- The new [`scrapy.downloadermiddlewares.retry.get_retry_request()`](../topics/downloader-middleware.md)
  function may be used from spider callbacks or middlewares to handle the
  retrying of a request beyond the scenarios that
  [`RetryMiddleware`](../topics/downloader-middleware.md) supports.
  ([#3590](https://github.com/scrapy/scrapy/issues/3590), [#3685](https://github.com/scrapy/scrapy/issues/3685), [#4902](https://github.com/scrapy/scrapy/issues/4902))
- The new [`headers_received`](../topics/signals.md) signal gives early access
  to response headers and allows [stopping downloads](../topics/request-response.md "Stopping the download of a Response").
  ([#1772](https://github.com/scrapy/scrapy/issues/1772), [#4897](https://github.com/scrapy/scrapy/issues/4897))
- The new [`Response.protocol`](../topics/request-response.md)
  attribute gives access to the string that identifies the protocol used to
  download a response. ([#4878](https://github.com/scrapy/scrapy/issues/4878))
- [Stats](../topics/stats.md) now include the following entries that indicate
  the number of successes and failures in storing
  [feeds](../topics/feed-exports.md):
  ```
  feedexport/success_count/<storage type>
  feedexport/failed_count/<storage type>
  ```

  Where `<storage type>` is the feed storage backend class name, such as
  [`FileFeedStorage`](../topics/feed-exports.md) or
  [`FTPFeedStorage`](../topics/feed-exports.md).

  ([#3947](https://github.com/scrapy/scrapy/issues/3947), [#4850](https://github.com/scrapy/scrapy/issues/4850))
- The [`UrlLengthMiddleware`](../topics/spider-middleware.md) spider
  middleware now logs ignored URLs with `INFO` [logging level](https://docs.python.org/3/library/logging.html#levels) instead of `DEBUG`, and it now includes the following entry
  into [stats](../topics/stats.md) to keep track of the number of ignored
  URLs:
  ```
  urllength/request_ignored_count
  ```

  ([#5036](https://github.com/scrapy/scrapy/issues/5036))
- The
  [`HttpCompressionMiddleware`](../topics/downloader-middleware.md)
  downloader middleware now logs the number of decompressed responses and the
  total count of resulting bytes:
  ```
  httpcompression/response_bytes
  httpcompression/response_count
  ```

  ([#4797](https://github.com/scrapy/scrapy/issues/4797), [#4799](https://github.com/scrapy/scrapy/issues/4799))

### Bug fixes

- Fixed installation on PyPy installing PyDispatcher in addition to
  PyPyDispatcher, which could prevent Scrapy from working depending on which
  package got imported. ([#4710](https://github.com/scrapy/scrapy/issues/4710), [#4814](https://github.com/scrapy/scrapy/issues/4814))
- When inspecting a callback to check if it is a generator that also returns
  a value, an exception is no longer raised if the callback has a docstring
  with lower indentation than the following code.
  ([#4477](https://github.com/scrapy/scrapy/issues/4477), [#4935](https://github.com/scrapy/scrapy/issues/4935))
- The [Content-Length](https://datatracker.ietf.org/doc/html/rfc2616#section-14.13)
  header is no longer omitted from responses when using the default, HTTP/1.1
  download handler (see [`DOWNLOAD_HANDLERS`](../topics/settings.md)).
  ([#5009](https://github.com/scrapy/scrapy/issues/5009), [#5034](https://github.com/scrapy/scrapy/issues/5034), [#5045](https://github.com/scrapy/scrapy/issues/5045), [#5057](https://github.com/scrapy/scrapy/issues/5057), [#5062](https://github.com/scrapy/scrapy/issues/5062))
- Setting the [`handle_httpstatus_all`](../topics/spider-middleware.md) request meta key to `False`
  now has the same effect as not setting it at all, instead of having the
  same effect as setting it to `True`.
  ([#3851](https://github.com/scrapy/scrapy/issues/3851), [#4694](https://github.com/scrapy/scrapy/issues/4694))

### Documentation

- Added instructions to [install Scrapy in Windows using pip](../intro/install.md "Windows").
  ([#4715](https://github.com/scrapy/scrapy/issues/4715), [#4736](https://github.com/scrapy/scrapy/issues/4736))
- Logging documentation now includes [additional ways to filter logs](../topics/logging.md "Advanced customization").
  ([#4216](https://github.com/scrapy/scrapy/issues/4216), [#4257](https://github.com/scrapy/scrapy/issues/4257), [#4965](https://github.com/scrapy/scrapy/issues/4965))
- Covered how to deal with long lists of allowed domains in the [FAQ](../faq.md). ([#2263](https://github.com/scrapy/scrapy/issues/2263), [#3667](https://github.com/scrapy/scrapy/issues/3667))
- Covered [scrapy-bench](https://github.com/scrapy/scrapy-bench) in [Benchmarking](../topics/benchmarking.md).
  ([#4996](https://github.com/scrapy/scrapy/issues/4996), [#5016](https://github.com/scrapy/scrapy/issues/5016))
- Clarified that one [extension](../topics/extensions.md) instance is created
  per crawler.
  ([#5014](https://github.com/scrapy/scrapy/issues/5014))
- Fixed some errors in examples.
  ([#4829](https://github.com/scrapy/scrapy/issues/4829), [#4830](https://github.com/scrapy/scrapy/issues/4830), [#4907](https://github.com/scrapy/scrapy/issues/4907), [#4909](https://github.com/scrapy/scrapy/issues/4909),
  [#5008](https://github.com/scrapy/scrapy/issues/5008))
- Fixed some external links, typos, and so on.
  ([#4892](https://github.com/scrapy/scrapy/issues/4892), [#4899](https://github.com/scrapy/scrapy/issues/4899), [#4936](https://github.com/scrapy/scrapy/issues/4936), [#4942](https://github.com/scrapy/scrapy/issues/4942), [#5005](https://github.com/scrapy/scrapy/issues/5005),
  [#5063](https://github.com/scrapy/scrapy/issues/5063))
- The [list of Request.meta keys](../topics/request-response.md "Request.meta special keys") is now sorted
  alphabetically.
  ([#5061](https://github.com/scrapy/scrapy/issues/5061), [#5065](https://github.com/scrapy/scrapy/issues/5065))
- Updated references to Scrapinghub, which is now called Zyte.
  ([#4973](https://github.com/scrapy/scrapy/issues/4973), [#5072](https://github.com/scrapy/scrapy/issues/5072))
- Added a mention to contributors in the README. ([#4956](https://github.com/scrapy/scrapy/issues/4956))
- Reduced the top margin of lists. ([#4974](https://github.com/scrapy/scrapy/issues/4974))

### Quality Assurance

- Made Python 3.9 support official ([#4757](https://github.com/scrapy/scrapy/issues/4757), [#4759](https://github.com/scrapy/scrapy/issues/4759))
- Extended typing hints ([#4895](https://github.com/scrapy/scrapy/issues/4895))
- Fixed deprecated uses of the Twisted API.
  ([#4940](https://github.com/scrapy/scrapy/issues/4940), [#4950](https://github.com/scrapy/scrapy/issues/4950), [#5073](https://github.com/scrapy/scrapy/issues/5073))
- Made our tests run with the new pip resolver.
  ([#4710](https://github.com/scrapy/scrapy/issues/4710), [#4814](https://github.com/scrapy/scrapy/issues/4814))
- Added tests to ensure that [coroutine support](../topics/coroutines.md "Supported callables")
  is tested. ([#4987](https://github.com/scrapy/scrapy/issues/4987))
- Migrated from Travis CI to GitHub Actions. ([#4924](https://github.com/scrapy/scrapy/issues/4924))
- Fixed CI issues.
  ([#4986](https://github.com/scrapy/scrapy/issues/4986), [#5020](https://github.com/scrapy/scrapy/issues/5020), [#5022](https://github.com/scrapy/scrapy/issues/5022), [#5027](https://github.com/scrapy/scrapy/issues/5027), [#5052](https://github.com/scrapy/scrapy/issues/5052),
  [#5053](https://github.com/scrapy/scrapy/issues/5053))
- Implemented code refactorings, style fixes and cleanups.
  ([#4911](https://github.com/scrapy/scrapy/issues/4911), [#4982](https://github.com/scrapy/scrapy/issues/4982), [#5001](https://github.com/scrapy/scrapy/issues/5001), [#5002](https://github.com/scrapy/scrapy/issues/5002), [#5076](https://github.com/scrapy/scrapy/issues/5076))

## Scrapy 2.4.1 (2020-11-17)

- Fixed [feed exports](../topics/feed-exports.md) overwrite support ([#4845](https://github.com/scrapy/scrapy/issues/4845), [#4857](https://github.com/scrapy/scrapy/issues/4857), [#4859](https://github.com/scrapy/scrapy/issues/4859))
- Fixed the AsyncIO event loop handling, which could make code hang
  ([#4855](https://github.com/scrapy/scrapy/issues/4855), [#4872](https://github.com/scrapy/scrapy/issues/4872))
- Fixed the IPv6-capable DNS resolver
  `CachingHostnameResolver` for download handlers
  that call
  [`reactor.resolve`](https://docs.twisted.org/en/stable/api/twisted.internet.interfaces.IReactorCore.html#resolve)
  ([#4802](https://github.com/scrapy/scrapy/issues/4802), [#4803](https://github.com/scrapy/scrapy/issues/4803))
- Fixed the output of the [`genspider`](../topics/commands.md) command showing placeholders
  instead of the import path of the generated spider module ([#4874](https://github.com/scrapy/scrapy/issues/4874))
- Migrated Windows CI from Azure Pipelines to GitHub Actions ([#4869](https://github.com/scrapy/scrapy/issues/4869),
  [#4876](https://github.com/scrapy/scrapy/issues/4876))

## Scrapy 2.4.0 (2020-10-11)

Highlights:

* Python 3.5 support has been dropped.
* The `file_path` method of [media pipelines](../topics/media-pipeline.md)
  can now access the source [item](../topics/items.md).

  This allows you to set a download file path based on item data.
* The new `item_export_kwargs` key of the [`FEEDS`](../topics/feed-exports.md) setting allows
  to define keyword parameters to pass to [item exporter classes](../topics/exporters.md)
* You can now choose whether [feed exports](../topics/feed-exports.md)
  overwrite or append to the output file.

  For example, when using the [`crawl`](../topics/commands.md) or [`runspider`](../topics/commands.md)
  commands, you can use the `-O` option instead of `-o` to overwrite the
  output file.
* Zstd-compressed responses are now supported if [zstandard](https://pypi.org/project/zstandard/) is installed.
* In settings, where the import path of a class is required, it is now
  possible to pass a class object instead.

### Modified requirements

* Python 3.6 or greater is now required; support for Python 3.5 has been
  dropped

  As a result:
  - When using PyPy, PyPy 7.2.0 or greater [is now required](../intro/install.md "Supported Python versions")
  - For Amazon S3 storage support in [feed exports](../topics/feed-exports.md "S3") or [media pipelines](../topics/media-pipeline.md "Amazon S3 storage"), [botocore](https://github.com/boto/botocore) 1.4.87 or greater is now required
  - To use the [images pipeline](../topics/media-pipeline.md "Using the Images Pipeline"), [Pillow](https://github.com/python-pillow/Pillow) 4.0.0 or
    greater is now required

  ([#4718](https://github.com/scrapy/scrapy/issues/4718), [#4732](https://github.com/scrapy/scrapy/issues/4732), [#4733](https://github.com/scrapy/scrapy/issues/4733), [#4742](https://github.com/scrapy/scrapy/issues/4742), [#4743](https://github.com/scrapy/scrapy/issues/4743),
  [#4764](https://github.com/scrapy/scrapy/issues/4764))

### Backward-incompatible changes

* [`CookiesMiddleware`](../topics/cookies.md) once again
  discards cookies defined in [`Request.headers`](../topics/request-response.md).

  We decided to revert this bug fix, introduced in Scrapy 2.2.0, because it
  was reported that the current implementation could break existing code.

  If you need to set cookies for a request, use the [`Request.cookies`](../topics/request-response.md) parameter.

  A future version of Scrapy will include a new, better implementation of the
  reverted bug fix.

  ([#4717](https://github.com/scrapy/scrapy/issues/4717), [#4823](https://github.com/scrapy/scrapy/issues/4823))

### Deprecation removals

* [`scrapy.extensions.feedexport.S3FeedStorage`](../topics/feed-exports.md) no longer reads the
  values of `access_key` and `secret_key` from the running project
  settings when they are not passed to its `__init__` method; you must
  either pass those parameters to its `__init__` method or use
  `S3FeedStorage.from_crawler`
  ([#4356](https://github.com/scrapy/scrapy/issues/4356), [#4411](https://github.com/scrapy/scrapy/issues/4411), [#4688](https://github.com/scrapy/scrapy/issues/4688))
* `Rule.process_request`
  no longer admits callables which expect a single `request` parameter,
  rather than both `request` and `response` ([#4818](https://github.com/scrapy/scrapy/issues/4818))

### Deprecations

* In custom [media pipelines](../topics/media-pipeline.md), signatures that
  do not accept a keyword-only `item` parameter in any of the  methods that
  now support this parameter are now
  deprecated ([#4628](https://github.com/scrapy/scrapy/issues/4628), [#4686](https://github.com/scrapy/scrapy/issues/4686))
* In custom [feed storage backend classes](../topics/feed-exports.md "Storages"),
  `__init__` method signatures that do not accept a keyword-only
  `feed_options` parameter are now deprecated ([#547](https://github.com/scrapy/scrapy/issues/547), [#716](https://github.com/scrapy/scrapy/issues/716),
  [#4512](https://github.com/scrapy/scrapy/issues/4512))
* The `scrapy.utils.python.WeakKeyCache` class is now deprecated
  ([#4684](https://github.com/scrapy/scrapy/issues/4684), [#4701](https://github.com/scrapy/scrapy/issues/4701))
* The `scrapy.utils.boto.is_botocore()` function is now deprecated, use
  `scrapy.utils.boto.is_botocore_available()` instead ([#4734](https://github.com/scrapy/scrapy/issues/4734),
  [#4776](https://github.com/scrapy/scrapy/issues/4776))

### New features

* The following methods of [media pipelines](../topics/media-pipeline.md) now
  accept an `item` keyword-only parameter containing the source
  [item](../topics/items.md):
  - In [`scrapy.pipelines.files.FilesPipeline`](../topics/media-pipeline.md):
    - `file_downloaded()`
    - [`file_path()`](../topics/media-pipeline.md)
    - `media_downloaded()`
    - `media_to_download()`
  - In [`scrapy.pipelines.images.ImagesPipeline`](../topics/media-pipeline.md):
    - `file_downloaded()`
    - [`file_path()`](../topics/media-pipeline.md)
    - `get_images()`
    - `image_downloaded()`
    - `media_downloaded()`
    - `media_to_download()`

  ([#4628](https://github.com/scrapy/scrapy/issues/4628), [#4686](https://github.com/scrapy/scrapy/issues/4686))
* The new `item_export_kwargs` key of the [`FEEDS`](../topics/feed-exports.md) setting allows
  to define keyword parameters to pass to [item exporter classes](../topics/exporters.md) ([#4606](https://github.com/scrapy/scrapy/issues/4606), [#4768](https://github.com/scrapy/scrapy/issues/4768))
* [Feed exports](../topics/feed-exports.md) gained overwrite support:
  * When using the [`crawl`](../topics/commands.md) or [`runspider`](../topics/commands.md) commands, you
    can use the `-O` option instead of `-o` to overwrite the output
    file
  * You can use the `overwrite` key in the [`FEEDS`](../topics/feed-exports.md) setting to
    configure whether to overwrite the output file (`True`) or append to
    its content (`False`)
  * The `__init__` and `from_crawler` methods of [feed storage
    backend classes](../topics/feed-exports.md "Storages") now receive a new keyword-only
    parameter, `feed_options`, which is a dictionary of [feed
    options](../topics/feed-exports.md)

  ([#547](https://github.com/scrapy/scrapy/issues/547), [#716](https://github.com/scrapy/scrapy/issues/716), [#4512](https://github.com/scrapy/scrapy/issues/4512))
* Zstd-compressed responses are now supported if [zstandard](https://pypi.org/project/zstandard/) is installed
  ([#4831](https://github.com/scrapy/scrapy/issues/4831))
* In settings, where the import path of a class is required, it is now
  possible to pass a class object instead ([#3870](https://github.com/scrapy/scrapy/issues/3870), [#3873](https://github.com/scrapy/scrapy/issues/3873)).

  This includes also settings where only part of its value is made of an
  import path, such as [`DOWNLOADER_MIDDLEWARES`](../topics/settings.md) or
  [`DOWNLOAD_HANDLERS`](../topics/settings.md).
* [Downloader middlewares](../topics/downloader-middleware.md) can now
  override [`response.request`](../topics/request-response.md).

  If a [downloader middleware](../topics/downloader-middleware.md) returns
  a [`Response`](../topics/request-response.md) object from
  [`process_response()`](../topics/downloader-middleware.md)
  or
  [`process_exception()`](../topics/downloader-middleware.md)
  with a custom [`Request`](../topics/request-response.md) object assigned to
  [`response.request`](../topics/request-response.md):
  - The response is handled by the callback of that custom
    [`Request`](../topics/request-response.md) object, instead of being handled by the
    callback of the original [`Request`](../topics/request-response.md) object
  - That custom [`Request`](../topics/request-response.md) object is now sent as the
    `request` argument to the [`response_received`](../topics/signals.md) signal, instead
    of the original [`Request`](../topics/request-response.md) object

  ([#4529](https://github.com/scrapy/scrapy/issues/4529), [#4632](https://github.com/scrapy/scrapy/issues/4632))
* When using the [FTP feed storage backend](../topics/feed-exports.md "FTP"):
  - It is now possible to set the new `overwrite` [feed option](../topics/feed-exports.md) to `False` to append to an existing file instead of
    overwriting it
  - The FTP password can now be omitted if it is not necessary

  ([#547](https://github.com/scrapy/scrapy/issues/547), [#716](https://github.com/scrapy/scrapy/issues/716), [#4512](https://github.com/scrapy/scrapy/issues/4512))
* The `__init__` method of [`CsvItemExporter`](../topics/exporters.md) now
  supports an `errors` parameter to indicate how to handle encoding errors
  ([#4755](https://github.com/scrapy/scrapy/issues/4755))
* When [using asyncio](../topics/asyncio.md), it is now possible to
  [set a custom asyncio loop](../topics/asyncio.md "Using custom asyncio loops") ([#4306](https://github.com/scrapy/scrapy/issues/4306),
  [#4414](https://github.com/scrapy/scrapy/issues/4414))
* Serialized requests (see [Jobs: pausing and resuming crawls](../topics/jobs.md)) now support callbacks that are
  spider methods that delegate on other callable ([#4756](https://github.com/scrapy/scrapy/issues/4756))
* When a response is larger than [`DOWNLOAD_MAXSIZE`](../topics/settings.md), the logged
  message is now a warning, instead of an error ([#3874](https://github.com/scrapy/scrapy/issues/3874),
  [#3886](https://github.com/scrapy/scrapy/issues/3886), [#4752](https://github.com/scrapy/scrapy/issues/4752))

### Bug fixes

* The [`genspider`](../topics/commands.md) command no longer overwrites existing files
  unless the `--force` option is used ([#4561](https://github.com/scrapy/scrapy/issues/4561), [#4616](https://github.com/scrapy/scrapy/issues/4616),
  [#4623](https://github.com/scrapy/scrapy/issues/4623))
* Cookies with an empty value are no longer considered invalid cookies
  ([#4772](https://github.com/scrapy/scrapy/issues/4772))
* The [`runspider`](../topics/commands.md) command now supports files with the `.pyw` file
  extension ([#4643](https://github.com/scrapy/scrapy/issues/4643), [#4646](https://github.com/scrapy/scrapy/issues/4646))
* The [`HttpProxyMiddleware`](../topics/downloader-middleware.md)
  middleware now simply ignores unsupported proxy values ([#3331](https://github.com/scrapy/scrapy/issues/3331),
  [#4778](https://github.com/scrapy/scrapy/issues/4778))
* Checks for generator callbacks with a `return` statement no longer warn
  about `return` statements in nested functions ([#4720](https://github.com/scrapy/scrapy/issues/4720),
  [#4721](https://github.com/scrapy/scrapy/issues/4721))
* The system file mode creation mask no longer affects the permissions of
  files generated using the [`startproject`](../topics/commands.md) command ([#4722](https://github.com/scrapy/scrapy/issues/4722))
* `scrapy.utils.iterators.xmliter` now supports namespaced node names
  ([#861](https://github.com/scrapy/scrapy/issues/861), [#4746](https://github.com/scrapy/scrapy/issues/4746))
* [`Request`](../topics/request-response.md) objects can now have `about:` URLs, which can
  work when using a headless browser ([#4835](https://github.com/scrapy/scrapy/issues/4835))

### Documentation

* The [`FEED_URI_PARAMS`](../topics/feed-exports.md) setting is now documented ([#4671](https://github.com/scrapy/scrapy/issues/4671),
  [#4724](https://github.com/scrapy/scrapy/issues/4724))
* Improved the documentation of
  [link extractors](../topics/link-extractors.md) with an usage example from
  a spider callback and reference documentation for the
  [`Link`](../topics/link-extractors.md) class ([#4751](https://github.com/scrapy/scrapy/issues/4751), [#4775](https://github.com/scrapy/scrapy/issues/4775))
* Clarified the impact of [`CONCURRENT_REQUESTS`](../topics/settings.md) when using the
  [`CloseSpider`](../topics/extensions.md) extension
  ([#4836](https://github.com/scrapy/scrapy/issues/4836))
* Removed references to Python 2’s `unicode` type ([#4547](https://github.com/scrapy/scrapy/issues/4547),
  [#4703](https://github.com/scrapy/scrapy/issues/4703))
* We now have an [official deprecation policy](../versioning.md "Deprecation policy")
  ([#4705](https://github.com/scrapy/scrapy/issues/4705))
* Our [documentation policies](../contributing.md) now cover usage
  of Sphinx’s [`versionadded`](https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#directive-versionadded) and [`versionchanged`](https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#directive-versionchanged)
  directives, and we have removed usages referencing Scrapy 1.4.0 and earlier
  versions ([#3971](https://github.com/scrapy/scrapy/issues/3971), [#4310](https://github.com/scrapy/scrapy/issues/4310))
* Other documentation cleanups ([#4090](https://github.com/scrapy/scrapy/issues/4090), [#4782](https://github.com/scrapy/scrapy/issues/4782), [#4800](https://github.com/scrapy/scrapy/issues/4800),
  [#4801](https://github.com/scrapy/scrapy/issues/4801), [#4809](https://github.com/scrapy/scrapy/issues/4809), [#4816](https://github.com/scrapy/scrapy/issues/4816), [#4825](https://github.com/scrapy/scrapy/issues/4825))

### Quality assurance

* Extended typing hints ([#4243](https://github.com/scrapy/scrapy/issues/4243), [#4691](https://github.com/scrapy/scrapy/issues/4691))
* Added tests for the [`check`](../topics/commands.md) command ([#4663](https://github.com/scrapy/scrapy/issues/4663))
* Fixed test failures on Debian ([#4726](https://github.com/scrapy/scrapy/issues/4726), [#4727](https://github.com/scrapy/scrapy/issues/4727), [#4735](https://github.com/scrapy/scrapy/issues/4735))
* Improved Windows test coverage ([#4723](https://github.com/scrapy/scrapy/issues/4723))
* Switched to [formatted string literals](https://docs.python.org/3/reference/lexical_analysis.html#f-strings) where possible
  ([#4307](https://github.com/scrapy/scrapy/issues/4307), [#4324](https://github.com/scrapy/scrapy/issues/4324), [#4672](https://github.com/scrapy/scrapy/issues/4672))
* Modernized `super()` usage ([#4707](https://github.com/scrapy/scrapy/issues/4707))
* Other code and test cleanups ([#1790](https://github.com/scrapy/scrapy/issues/1790), [#3288](https://github.com/scrapy/scrapy/issues/3288), [#4165](https://github.com/scrapy/scrapy/issues/4165),
  [#4564](https://github.com/scrapy/scrapy/issues/4564), [#4651](https://github.com/scrapy/scrapy/issues/4651), [#4714](https://github.com/scrapy/scrapy/issues/4714), [#4738](https://github.com/scrapy/scrapy/issues/4738), [#4745](https://github.com/scrapy/scrapy/issues/4745),
  [#4747](https://github.com/scrapy/scrapy/issues/4747), [#4761](https://github.com/scrapy/scrapy/issues/4761), [#4765](https://github.com/scrapy/scrapy/issues/4765), [#4804](https://github.com/scrapy/scrapy/issues/4804), [#4817](https://github.com/scrapy/scrapy/issues/4817),
  [#4820](https://github.com/scrapy/scrapy/issues/4820), [#4822](https://github.com/scrapy/scrapy/issues/4822), [#4839](https://github.com/scrapy/scrapy/issues/4839))

## Scrapy 2.3.0 (2020-08-04)

Highlights:

* [Feed exports](../topics/feed-exports.md) now support [Google Cloud
  Storage](../topics/feed-exports.md "Google Cloud Storage (GCS)") as a storage backend
* The new [`FEED_EXPORT_BATCH_ITEM_COUNT`](../topics/feed-exports.md) setting allows to deliver
  output items in batches of up to the specified number of items.

  It also serves as a workaround for [delayed file delivery](../topics/feed-exports.md), which causes Scrapy to only start item delivery
  after the crawl has finished when using certain storage backends
  ([S3](../topics/feed-exports.md), [FTP](../topics/feed-exports.md),
  and now [GCS](../topics/feed-exports.md "Google Cloud Storage (GCS)")).
* The base implementation of [item loaders](../topics/loaders.md) has been
  moved into a separate library, [itemloaders](https://itemloaders.readthedocs.io/en/latest/index.html),
  allowing usage from outside Scrapy and a separate release schedule

### Deprecation removals

* Removed the following classes and their parent modules from
  `scrapy.linkextractors`:
  * `htmlparser.HtmlParserLinkExtractor`
  * `regex.RegexLinkExtractor`
  * `sgml.BaseSgmlLinkExtractor`
  * `sgml.SgmlLinkExtractor`

  Use
  [`LinkExtractor`](../topics/link-extractors.md)
  instead ([#4356](https://github.com/scrapy/scrapy/issues/4356), [#4679](https://github.com/scrapy/scrapy/issues/4679))

### Deprecations

* The `scrapy.utils.python.retry_on_eintr` function is now deprecated
  ([#4683](https://github.com/scrapy/scrapy/issues/4683))

### New features

* [Feed exports](../topics/feed-exports.md) support [Google Cloud
  Storage](../topics/feed-exports.md "Google Cloud Storage (GCS)") ([#685](https://github.com/scrapy/scrapy/issues/685), [#3608](https://github.com/scrapy/scrapy/issues/3608))
* New [`FEED_EXPORT_BATCH_ITEM_COUNT`](../topics/feed-exports.md) setting for batch deliveries
  ([#4250](https://github.com/scrapy/scrapy/issues/4250), [#4434](https://github.com/scrapy/scrapy/issues/4434))
* The [`parse`](../topics/commands.md) command now allows specifying an output file
  ([#4317](https://github.com/scrapy/scrapy/issues/4317), [#4377](https://github.com/scrapy/scrapy/issues/4377))
* [`Request.from_curl()`](../topics/request-response.md) and
  [`curl_to_request_kwargs()`](../topics/developer-tools.md) now also support
  `--data-raw` ([#4612](https://github.com/scrapy/scrapy/issues/4612))
* A `parse` callback may now be used in built-in spider subclasses, such
  as [`CrawlSpider`](../topics/spiders.md) ([#712](https://github.com/scrapy/scrapy/issues/712), [#732](https://github.com/scrapy/scrapy/issues/732),
  [#781](https://github.com/scrapy/scrapy/issues/781), [#4254](https://github.com/scrapy/scrapy/issues/4254) )

### Bug fixes

* Fixed the [CSV exporting](../topics/feed-exports.md "CSV") of
  [dataclass items](../topics/items.md "Dataclass objects") and [attr.s items](../topics/items.md "attr.s objects") ([#4667](https://github.com/scrapy/scrapy/issues/4667), [#4668](https://github.com/scrapy/scrapy/issues/4668))
* [`Request.from_curl()`](../topics/request-response.md) and
  [`curl_to_request_kwargs()`](../topics/developer-tools.md) now set the request
  method to `POST` when a request body is specified and no request method
  is specified ([#4612](https://github.com/scrapy/scrapy/issues/4612))
* The processing of ANSI escape sequences in enabled in Windows 10.0.14393
  and later, where it is required for colored output ([#4393](https://github.com/scrapy/scrapy/issues/4393),
  [#4403](https://github.com/scrapy/scrapy/issues/4403))

### Documentation

* Updated the [OpenSSL cipher list format](https://docs.openssl.org/master/man1/openssl-ciphers/#cipher-list-format) link in the documentation about
  the [`DOWNLOADER_CLIENT_TLS_CIPHERS`](../topics/settings.md) setting ([#4653](https://github.com/scrapy/scrapy/issues/4653))
* Simplified the code example in [Working with dataclass items](../topics/loaders.md)
  ([#4652](https://github.com/scrapy/scrapy/issues/4652))

### Quality assurance

* The base implementation of [item loaders](../topics/loaders.md) has been
  moved into [itemloaders](https://itemloaders.readthedocs.io/en/latest/index.html) ([#4005](https://github.com/scrapy/scrapy/issues/4005),
  [#4516](https://github.com/scrapy/scrapy/issues/4516))
* Fixed a silenced error in some scheduler tests ([#4644](https://github.com/scrapy/scrapy/issues/4644),
  [#4645](https://github.com/scrapy/scrapy/issues/4645))
* Renewed the localhost certificate used for SSL tests ([#4650](https://github.com/scrapy/scrapy/issues/4650))
* Removed cookie-handling code specific to Python 2 ([#4682](https://github.com/scrapy/scrapy/issues/4682))
* Stopped using Python 2 unicode literal syntax ([#4704](https://github.com/scrapy/scrapy/issues/4704))
* Stopped using a backlash for line continuation ([#4673](https://github.com/scrapy/scrapy/issues/4673))
* Removed unneeded entries from the MyPy exception list ([#4690](https://github.com/scrapy/scrapy/issues/4690))
* Automated tests now pass on Windows as part of our continuous integration
  system ([#4458](https://github.com/scrapy/scrapy/issues/4458))
* Automated tests now pass on the latest PyPy version for supported Python
  versions in our continuous integration system ([#4504](https://github.com/scrapy/scrapy/issues/4504))

## Scrapy 2.2.1 (2020-07-17)

* The [`startproject`](../topics/commands.md) command no longer makes unintended changes to
  the permissions of files in the destination folder, such as removing
  execution permissions ([#4662](https://github.com/scrapy/scrapy/issues/4662), [#4666](https://github.com/scrapy/scrapy/issues/4666))

## Scrapy 2.2.0 (2020-06-24)

Highlights:

* Python 3.5.2+ is required now
* [dataclass objects](../topics/items.md) and
  [attrs objects](../topics/items.md "attr.s objects") are now valid [item types](../topics/items.md)
* New [`TextResponse.json`](../topics/request-response.md) method
* New [`bytes_received`](../topics/signals.md) signal that allows canceling response download
* [`CookiesMiddleware`](../topics/cookies.md) fixes

### Backward-incompatible changes

* Support for Python 3.5.0 and 3.5.1 has been dropped; Scrapy now refuses to
  run with a Python version lower than 3.5.2, which introduced
  [`typing.Type`](https://docs.python.org/3/library/typing.html#typing.Type) ([#4615](https://github.com/scrapy/scrapy/issues/4615))

### Deprecations

* `TextResponse.body_as_unicode()` is now deprecated, use
  [`TextResponse.text`](../topics/request-response.md) instead
  ([#4546](https://github.com/scrapy/scrapy/issues/4546), [#4555](https://github.com/scrapy/scrapy/issues/4555), [#4579](https://github.com/scrapy/scrapy/issues/4579))
* `scrapy.item.BaseItem` is now deprecated, use
  [`scrapy.item.Item`](../topics/items.md) instead ([#4534](https://github.com/scrapy/scrapy/issues/4534))

### New features

* [dataclass objects](../topics/items.md) and
  [attrs objects](../topics/items.md "attr.s objects") are now valid [item types](../topics/items.md), and a new [itemadapter](https://github.com/scrapy/itemadapter) library makes it easy to
  write code that [supports any item type](../topics/items.md "Supporting All Item Types")
  ([#2749](https://github.com/scrapy/scrapy/issues/2749), [#2807](https://github.com/scrapy/scrapy/issues/2807), [#3761](https://github.com/scrapy/scrapy/issues/3761), [#3881](https://github.com/scrapy/scrapy/issues/3881), [#4642](https://github.com/scrapy/scrapy/issues/4642))
* A new [`TextResponse.json`](../topics/request-response.md) method
  allows to deserialize JSON responses ([#2444](https://github.com/scrapy/scrapy/issues/2444), [#4460](https://github.com/scrapy/scrapy/issues/4460),
  [#4574](https://github.com/scrapy/scrapy/issues/4574))
* A new [`bytes_received`](../topics/signals.md) signal allows monitoring response download
  progress and [stopping downloads](../topics/request-response.md "Stopping the download of a Response")
  ([#4205](https://github.com/scrapy/scrapy/issues/4205), [#4559](https://github.com/scrapy/scrapy/issues/4559))
* The dictionaries in the result list of a [media pipeline](../topics/media-pipeline.md) now include a new key, `status`, which indicates
  if the file was downloaded or, if the file was not downloaded, why it was
  not downloaded; see [`FilesPipeline.get_media_requests`](../topics/media-pipeline.md) for more
  information ([#2893](https://github.com/scrapy/scrapy/issues/2893), [#4486](https://github.com/scrapy/scrapy/issues/4486))
* When using [Google Cloud Storage](../topics/media-pipeline.md) for
  a [media pipeline](../topics/media-pipeline.md), a warning is now logged if
  the configured credentials do not grant the required permissions
  ([#4346](https://github.com/scrapy/scrapy/issues/4346), [#4508](https://github.com/scrapy/scrapy/issues/4508))
* [Link extractors](../topics/link-extractors.md) are now serializable,
  as long as you do not use [lambdas](https://docs.python.org/3/reference/expressions.html#lambda) for parameters; for
  example, you can now pass link extractors in [`Request.cb_kwargs`](../topics/request-response.md)
  or [`Request.meta`](../topics/request-response.md) when [persisting
  scheduled requests](../topics/jobs.md) ([#4554](https://github.com/scrapy/scrapy/issues/4554))
* Upgraded the [pickle protocol](https://docs.python.org/3/library/pickle.html#pickle-protocols) that Scrapy uses
  from protocol 2 to protocol 4, improving serialization capabilities and
  performance ([#4135](https://github.com/scrapy/scrapy/issues/4135), [#4541](https://github.com/scrapy/scrapy/issues/4541))
* `scrapy.utils.misc.create_instance()` now raises a `TypeError`
  exception if the resulting instance is `None` ([#4528](https://github.com/scrapy/scrapy/issues/4528),
  [#4532](https://github.com/scrapy/scrapy/issues/4532))

### Bug fixes

* [`CookiesMiddleware`](../topics/cookies.md) no longer
  discards cookies defined in [`Request.headers`](../topics/request-response.md) ([#1992](https://github.com/scrapy/scrapy/issues/1992), [#2400](https://github.com/scrapy/scrapy/issues/2400))
* [`CookiesMiddleware`](../topics/cookies.md) no longer
  re-encodes cookies defined as `bytes` in the `cookies` parameter
  of the `__init__` method of [`Request`](../topics/request-response.md)
  ([#2400](https://github.com/scrapy/scrapy/issues/2400), [#3575](https://github.com/scrapy/scrapy/issues/3575))
* When [`FEEDS`](../topics/feed-exports.md) defines multiple URIs, [`FEED_STORE_EMPTY`](../topics/feed-exports.md) is
  `False` and the crawl yields no items, Scrapy no longer stops feed
  exports after the first URI ([#4621](https://github.com/scrapy/scrapy/issues/4621), [#4626](https://github.com/scrapy/scrapy/issues/4626))
* [`Spider`](../topics/spiders.md) callbacks defined using [coroutine
  syntax](https://docs.scrapy.org/en/latest/topics/coroutines.md) no longer need to return an iterable, and may
  instead return a [`Request`](../topics/request-response.md) object, an
  [item](../topics/items.md), or `None` ([#4609](https://github.com/scrapy/scrapy/issues/4609))
* The [`startproject`](../topics/commands.md) command now ensures that the generated project
  folders and files have the right permissions ([#4604](https://github.com/scrapy/scrapy/issues/4604))
* Fix a `KeyError` exception being sometimes raised from
  `scrapy.utils.datatypes.LocalWeakReferencedCache` ([#4597](https://github.com/scrapy/scrapy/issues/4597),
  [#4599](https://github.com/scrapy/scrapy/issues/4599))
* When [`FEEDS`](../topics/feed-exports.md) defines multiple URIs, log messages about items being
  stored now contain information from the corresponding feed, instead of
  always containing information about only one of the feeds ([#4619](https://github.com/scrapy/scrapy/issues/4619),
  [#4629](https://github.com/scrapy/scrapy/issues/4629))

### Documentation

* Added a new section about [accessing cb_kwargs from errbacks](../topics/request-response.md "Accessing additional data in errback functions") ([#4598](https://github.com/scrapy/scrapy/issues/4598), [#4634](https://github.com/scrapy/scrapy/issues/4634))
* Covered [chompjs](https://github.com/Nykakin/chompjs) in [Parsing JavaScript code](../topics/dynamic-content.md) ([#4556](https://github.com/scrapy/scrapy/issues/4556),
  [#4562](https://github.com/scrapy/scrapy/issues/4562))
* Removed from [Coroutines](https://docs.scrapy.org/en/latest/topics/coroutines.md) the warning about the API being
  experimental ([#4511](https://github.com/scrapy/scrapy/issues/4511), [#4513](https://github.com/scrapy/scrapy/issues/4513))
* Removed references to unsupported versions of [Twisted](https://docs.twisted.org/en/stable/index.html) ([#4533](https://github.com/scrapy/scrapy/issues/4533))
* Updated the description of the [screenshot pipeline example](../topics/item-pipeline.md "Take a screenshot of an item"), which now uses [coroutine syntax](https://docs.scrapy.org/en/latest/topics/coroutines.md) instead of returning a
  [`Deferred`](https://docs.twisted.org/en/stable/api/twisted.internet.defer.Deferred.html) ([#4514](https://github.com/scrapy/scrapy/issues/4514), [#4593](https://github.com/scrapy/scrapy/issues/4593))
* Removed a misleading import line from the
  [`scrapy.utils.log.configure_logging()`](../topics/logging.md) code example ([#4510](https://github.com/scrapy/scrapy/issues/4510),
  [#4587](https://github.com/scrapy/scrapy/issues/4587))
* The display-on-hover behavior of internal documentation references now also
  covers links to [commands](../topics/commands.md), [`Request.meta`](../topics/request-response.md)
  keys, [settings](../topics/settings.md) and
  [signals](../topics/signals.md) ([#4495](https://github.com/scrapy/scrapy/issues/4495), [#4563](https://github.com/scrapy/scrapy/issues/4563))
* It is again possible to download the documentation for offline reading
  ([#4578](https://github.com/scrapy/scrapy/issues/4578), [#4585](https://github.com/scrapy/scrapy/issues/4585))
* Removed backslashes preceding `*args` and `**kwargs` in some function
  and method signatures ([#4592](https://github.com/scrapy/scrapy/issues/4592), [#4596](https://github.com/scrapy/scrapy/issues/4596))

### Quality assurance

* Adjusted the code base further to our [style guidelines](../contributing.md "Coding style") ([#4237](https://github.com/scrapy/scrapy/issues/4237), [#4525](https://github.com/scrapy/scrapy/issues/4525), [#4538](https://github.com/scrapy/scrapy/issues/4538),
  [#4539](https://github.com/scrapy/scrapy/issues/4539), [#4540](https://github.com/scrapy/scrapy/issues/4540), [#4542](https://github.com/scrapy/scrapy/issues/4542), [#4543](https://github.com/scrapy/scrapy/issues/4543), [#4544](https://github.com/scrapy/scrapy/issues/4544),
  [#4545](https://github.com/scrapy/scrapy/issues/4545), [#4557](https://github.com/scrapy/scrapy/issues/4557), [#4558](https://github.com/scrapy/scrapy/issues/4558), [#4566](https://github.com/scrapy/scrapy/issues/4566), [#4568](https://github.com/scrapy/scrapy/issues/4568),
  [#4572](https://github.com/scrapy/scrapy/issues/4572))
* Removed remnants of Python 2 support ([#4550](https://github.com/scrapy/scrapy/issues/4550), [#4553](https://github.com/scrapy/scrapy/issues/4553),
  [#4568](https://github.com/scrapy/scrapy/issues/4568))
* Improved code sharing between the [`crawl`](../topics/commands.md) and [`runspider`](../topics/commands.md)
  commands ([#4548](https://github.com/scrapy/scrapy/issues/4548), [#4552](https://github.com/scrapy/scrapy/issues/4552))
* Replaced `chain(*iterable)` with `chain.from_iterable(iterable)`
  ([#4635](https://github.com/scrapy/scrapy/issues/4635))
* You may now run the [`asyncio`](https://docs.python.org/3/library/asyncio.html#module-asyncio) tests with Tox on any Python version
  ([#4521](https://github.com/scrapy/scrapy/issues/4521))
* Updated test requirements to reflect an incompatibility with pytest 5.4 and
  5.4.1 ([#4588](https://github.com/scrapy/scrapy/issues/4588))
* Improved [`SpiderLoader`](../topics/api.md) test coverage for
  scenarios involving duplicate spider names ([#4549](https://github.com/scrapy/scrapy/issues/4549), [#4560](https://github.com/scrapy/scrapy/issues/4560))
* Configured Travis CI to also run the tests with Python 3.5.2
  ([#4518](https://github.com/scrapy/scrapy/issues/4518), [#4615](https://github.com/scrapy/scrapy/issues/4615))
* Added a [Pylint](https://www.pylint.org/) job to Travis CI
  ([#3727](https://github.com/scrapy/scrapy/issues/3727))
* Added a [Mypy](https://mypy-lang.org/) job to Travis CI ([#4637](https://github.com/scrapy/scrapy/issues/4637))
* Made use of set literals in tests ([#4573](https://github.com/scrapy/scrapy/issues/4573))
* Cleaned up the Travis CI configuration ([#4517](https://github.com/scrapy/scrapy/issues/4517), [#4519](https://github.com/scrapy/scrapy/issues/4519),
  [#4522](https://github.com/scrapy/scrapy/issues/4522), [#4537](https://github.com/scrapy/scrapy/issues/4537))

## Scrapy 2.1.0 (2020-04-24)

Highlights:

* New [`FEEDS`](../topics/feed-exports.md) setting to export to multiple feeds
* New [`Response.ip_address`](../topics/request-response.md) attribute

### Backward-incompatible changes

* `AssertionError` exceptions triggered by [assert](https://docs.python.org/3/reference/simple_stmts.html#assert)
  statements have been replaced by new exception types, to support running
  Python in optimized mode (see [`-O`](https://docs.python.org/3/using/cmdline.html#cmdoption-O)) without changing Scrapy’s
  behavior in any unexpected ways.

  If you catch an `AssertionError` exception from Scrapy, update your
  code to catch the corresponding new exception.

  ([#4440](https://github.com/scrapy/scrapy/issues/4440))

### Deprecation removals

* The `LOG_UNSERIALIZABLE_REQUESTS` setting is no longer supported, use
  [`SCHEDULER_DEBUG`](../topics/settings.md) instead ([#4385](https://github.com/scrapy/scrapy/issues/4385))
* The `REDIRECT_MAX_METAREFRESH_DELAY` setting is no longer supported, use
  [`METAREFRESH_MAXDELAY`](../topics/downloader-middleware.md) instead ([#4385](https://github.com/scrapy/scrapy/issues/4385))
* The `ChunkedTransferMiddleware`
  middleware has been removed, including the entire
  `scrapy.downloadermiddlewares.chunked` module; chunked transfers
  work out of the box ([#4431](https://github.com/scrapy/scrapy/issues/4431))
* The `spiders` property has been removed from
  [`Crawler`](../topics/api.md), use `CrawlerRunner.spider_loader` or instantiate
  [`SPIDER_LOADER_CLASS`](../topics/settings.md) with your settings instead ([#4398](https://github.com/scrapy/scrapy/issues/4398))
* The `MultiValueDict`, `MultiValueDictKeyError`, and `SiteNode`
  classes have been removed from `scrapy.utils.datatypes`
  ([#4400](https://github.com/scrapy/scrapy/issues/4400))

### Deprecations

* The `FEED_FORMAT` and `FEED_URI` settings have been deprecated in
  favor of the new [`FEEDS`](../topics/feed-exports.md) setting ([#1336](https://github.com/scrapy/scrapy/issues/1336), [#3858](https://github.com/scrapy/scrapy/issues/3858),
  [#4507](https://github.com/scrapy/scrapy/issues/4507))

### New features

* A new setting, [`FEEDS`](../topics/feed-exports.md), allows configuring multiple output feeds
  with different settings each ([#1336](https://github.com/scrapy/scrapy/issues/1336), [#3858](https://github.com/scrapy/scrapy/issues/3858), [#4507](https://github.com/scrapy/scrapy/issues/4507))
* The [`crawl`](../topics/commands.md) and [`runspider`](../topics/commands.md) commands now support multiple
  `-o` parameters ([#1336](https://github.com/scrapy/scrapy/issues/1336), [#3858](https://github.com/scrapy/scrapy/issues/3858), [#4507](https://github.com/scrapy/scrapy/issues/4507))
* The [`crawl`](../topics/commands.md) and [`runspider`](../topics/commands.md) commands now support
  specifying an output format by appending `:<format>` to the output file
  ([#1336](https://github.com/scrapy/scrapy/issues/1336), [#3858](https://github.com/scrapy/scrapy/issues/3858), [#4507](https://github.com/scrapy/scrapy/issues/4507))
* The new [`Response.ip_address`](../topics/request-response.md)
  attribute gives access to the IP address that originated a response
  ([#3903](https://github.com/scrapy/scrapy/issues/3903), [#3940](https://github.com/scrapy/scrapy/issues/3940))
* A warning is now issued when a value in
  `allowed_domains` includes a port
  ([#50](https://github.com/scrapy/scrapy/issues/50), [#3198](https://github.com/scrapy/scrapy/issues/3198), [#4413](https://github.com/scrapy/scrapy/issues/4413))
* Zsh completion now excludes used option aliases from the completion list
  ([#4438](https://github.com/scrapy/scrapy/issues/4438))

### Bug fixes

* [Request serialization](../topics/jobs.md) no longer breaks for
  callbacks that are spider attributes which are assigned a function with a
  different name ([#4500](https://github.com/scrapy/scrapy/issues/4500))
* `None` values in `allowed_domains` no longer
  cause a `TypeError` exception ([#4410](https://github.com/scrapy/scrapy/issues/4410))
* Zsh completion no longer allows options after arguments ([#4438](https://github.com/scrapy/scrapy/issues/4438))
* zope.interface 5.0.0 and later versions are now supported
  ([#4447](https://github.com/scrapy/scrapy/issues/4447), [#4448](https://github.com/scrapy/scrapy/issues/4448))
* `Spider.make_requests_from_url`, deprecated in Scrapy 1.4.0, now issues a
  warning when used ([#4412](https://github.com/scrapy/scrapy/issues/4412))

### Documentation

* Improved the documentation about signals that allow their handlers to
  return a [`Deferred`](https://docs.twisted.org/en/stable/api/twisted.internet.defer.Deferred.html) ([#4295](https://github.com/scrapy/scrapy/issues/4295),
  [#4390](https://github.com/scrapy/scrapy/issues/4390))
* Our PyPI entry now includes links for our documentation, our source code
  repository and our issue tracker ([#4456](https://github.com/scrapy/scrapy/issues/4456))
* Covered the [curl2scrapy](https://michael-shub.github.io/curl2scrapy/)
  service in the documentation ([#4206](https://github.com/scrapy/scrapy/issues/4206), [#4455](https://github.com/scrapy/scrapy/issues/4455))
* Removed references to the Guppy library, which only works in Python 2
  ([#4285](https://github.com/scrapy/scrapy/issues/4285), [#4343](https://github.com/scrapy/scrapy/issues/4343))
* Extended use of InterSphinx to link to Python 3 documentation
  ([#4444](https://github.com/scrapy/scrapy/issues/4444), [#4445](https://github.com/scrapy/scrapy/issues/4445))
* Added support for Sphinx 3.0 and later ([#4475](https://github.com/scrapy/scrapy/issues/4475), [#4480](https://github.com/scrapy/scrapy/issues/4480),
  [#4496](https://github.com/scrapy/scrapy/issues/4496), [#4503](https://github.com/scrapy/scrapy/issues/4503))

### Quality assurance

* Removed warnings about using old, removed settings ([#4404](https://github.com/scrapy/scrapy/issues/4404))
* Removed a warning about importing
  [`StringTransport`](https://docs.twisted.org/en/stable/api/twisted.internet.testing.StringTransport.html) from
  `twisted.test.proto_helpers` in Twisted 19.7.0 or newer ([#4409](https://github.com/scrapy/scrapy/issues/4409))
* Removed outdated Debian package build files ([#4384](https://github.com/scrapy/scrapy/issues/4384))
* Removed `object` usage as a base class ([#4430](https://github.com/scrapy/scrapy/issues/4430))
* Removed code that added support for old versions of Twisted that we no
  longer support ([#4472](https://github.com/scrapy/scrapy/issues/4472))
* Fixed code style issues ([#4468](https://github.com/scrapy/scrapy/issues/4468), [#4469](https://github.com/scrapy/scrapy/issues/4469), [#4471](https://github.com/scrapy/scrapy/issues/4471),
  [#4481](https://github.com/scrapy/scrapy/issues/4481))
* Removed [`twisted.internet.defer.returnValue()`](https://docs.twisted.org/en/stable/api/twisted.internet.defer.html#returnValue) calls ([#4443](https://github.com/scrapy/scrapy/issues/4443),
  [#4446](https://github.com/scrapy/scrapy/issues/4446), [#4489](https://github.com/scrapy/scrapy/issues/4489))

## Scrapy 2.0.1 (2020-03-18)

* [`Response.follow_all`](../topics/request-response.md) now supports
  an empty URL iterable as input ([#4408](https://github.com/scrapy/scrapy/issues/4408), [#4420](https://github.com/scrapy/scrapy/issues/4420))
* Removed top-level [`reactor`](https://docs.twisted.org/en/stable/api/twisted.internet.reactor.html) imports to prevent
  errors about the wrong Twisted reactor being installed when setting a
  different Twisted reactor using `TWISTED_REACTOR` ([#4401](https://github.com/scrapy/scrapy/issues/4401),
  [#4406](https://github.com/scrapy/scrapy/issues/4406))
* Fixed tests ([#4422](https://github.com/scrapy/scrapy/issues/4422))

## Scrapy 2.0.0 (2020-03-03)

Highlights:

* Python 2 support has been removed
* [Partial](https://docs.scrapy.org/en/latest/topics/coroutines.md) [coroutine syntax](https://docs.python.org/3/reference/compound_stmts.html#async) support
  and [experimental](https://docs.scrapy.org/en/latest/topics/asyncio.md) [`asyncio`](https://docs.python.org/3/library/asyncio.html#module-asyncio) support
* New [`Response.follow_all`](../topics/request-response.md) method
* [FTP support](../topics/media-pipeline.md "FTP server storage") for media pipelines
* New [`Response.certificate`](../topics/request-response.md)
  attribute
* IPv6 support through `DNS_RESOLVER`

### Backward-incompatible changes

* Python 2 support has been removed, following [Python 2 end-of-life on
  January 1, 2020](https://www.python.org/doc/sunset-python-2/) ([#4091](https://github.com/scrapy/scrapy/issues/4091), [#4114](https://github.com/scrapy/scrapy/issues/4114), [#4115](https://github.com/scrapy/scrapy/issues/4115),
  [#4121](https://github.com/scrapy/scrapy/issues/4121), [#4138](https://github.com/scrapy/scrapy/issues/4138), [#4231](https://github.com/scrapy/scrapy/issues/4231), [#4242](https://github.com/scrapy/scrapy/issues/4242), [#4304](https://github.com/scrapy/scrapy/issues/4304),
  [#4309](https://github.com/scrapy/scrapy/issues/4309), [#4373](https://github.com/scrapy/scrapy/issues/4373))
* Retry gaveups (see [`RETRY_TIMES`](../topics/downloader-middleware.md)) are now logged as errors instead
  of as debug information ([#3171](https://github.com/scrapy/scrapy/issues/3171), [#3566](https://github.com/scrapy/scrapy/issues/3566))
* File extensions that
  [`LinkExtractor`](../topics/link-extractors.md)
  ignores by default now also include `7z`, `7zip`, `apk`, `bz2`,
  `cdr`, `dmg`, `ico`, `iso`, `tar`, `tar.gz`, `webm`, and
  `xz` ([#1837](https://github.com/scrapy/scrapy/issues/1837), [#2067](https://github.com/scrapy/scrapy/issues/2067), [#4066](https://github.com/scrapy/scrapy/issues/4066))
* The [`METAREFRESH_IGNORE_TAGS`](https://docs.scrapy.org/en/latest/topics/downloader-middleware.md#std-setting-METAREFRESH_IGNORE_TAGS) setting is now an empty list by
  default, following web browser behavior ([#3844](https://github.com/scrapy/scrapy/issues/3844), [#4311](https://github.com/scrapy/scrapy/issues/4311))
* The
  [`HttpCompressionMiddleware`](../topics/downloader-middleware.md)
  now includes spaces after commas in the value of the `Accept-Encoding`
  header that it sets, following web browser behavior ([#4293](https://github.com/scrapy/scrapy/issues/4293))
* The `__init__` method of custom download handlers (see
  [`DOWNLOAD_HANDLERS`](../topics/settings.md)) or subclasses of the following downloader
  handlers  no longer receives a `settings` parameter:
  * [`scrapy.core.downloader.handlers.datauri.DataURIDownloadHandler`](../topics/download-handlers.md)
  * [`scrapy.core.downloader.handlers.file.FileDownloadHandler`](../topics/download-handlers.md)

  Use the `from_settings` or `from_crawler` class methods to expose such
  a parameter to your custom download handlers.

  ([#4126](https://github.com/scrapy/scrapy/issues/4126))
* We have refactored the [`scrapy.core.scheduler.Scheduler`](../topics/scheduler.md) class and
  related queue classes (see [`SCHEDULER_PRIORITY_QUEUE`](../topics/settings.md),
  [`SCHEDULER_DISK_QUEUE`](../topics/settings.md) and [`SCHEDULER_MEMORY_QUEUE`](../topics/settings.md)) to
  make it easier to implement custom scheduler queue classes. See
  Changes to scheduler queue classes below for details.
* Overridden settings are now logged in a different format. This is more in
  line with similar information logged at startup ([#4199](https://github.com/scrapy/scrapy/issues/4199))

### Deprecation removals

* The [Scrapy shell](../topics/shell.md) no longer provides a sel proxy
  object, use [`response.selector`](../topics/request-response.md)
  instead ([#4347](https://github.com/scrapy/scrapy/issues/4347))
* LevelDB support has been removed ([#4112](https://github.com/scrapy/scrapy/issues/4112))
* The following functions have been removed from `scrapy.utils.python`:
  `isbinarytext`, `is_writable`, `setattr_default`, `stringify_dict`
  ([#4362](https://github.com/scrapy/scrapy/issues/4362))

### Deprecations

* Using environment variables prefixed with `SCRAPY_` to override settings
  is deprecated ([#4300](https://github.com/scrapy/scrapy/issues/4300), [#4374](https://github.com/scrapy/scrapy/issues/4374), [#4375](https://github.com/scrapy/scrapy/issues/4375))
* `scrapy.linkextractors.FilteringLinkExtractor` is deprecated, use
  [`scrapy.linkextractors.LinkExtractor`](../topics/link-extractors.md) instead ([#4045](https://github.com/scrapy/scrapy/issues/4045))
* The `noconnect` query string argument of proxy URLs is deprecated and
  should be removed from proxy URLs ([#4198](https://github.com/scrapy/scrapy/issues/4198))
* The `next` method of
  `scrapy.utils.python.MutableChain` is deprecated, use the global
  `next()` function or `MutableChain.__next__` instead ([#4153](https://github.com/scrapy/scrapy/issues/4153))

### New features

* Added [partial support](https://docs.scrapy.org/en/latest/topics/coroutines.md) for Python’s
  [coroutine syntax](https://docs.python.org/3/reference/compound_stmts.html#async) and [experimental support](https://docs.scrapy.org/en/latest/topics/asyncio.md) for [`asyncio`](https://docs.python.org/3/library/asyncio.html#module-asyncio) and [`asyncio`](https://docs.python.org/3/library/asyncio.html#module-asyncio)-powered libraries
  ([#4010](https://github.com/scrapy/scrapy/issues/4010), [#4259](https://github.com/scrapy/scrapy/issues/4259), [#4269](https://github.com/scrapy/scrapy/issues/4269), [#4270](https://github.com/scrapy/scrapy/issues/4270), [#4271](https://github.com/scrapy/scrapy/issues/4271),
  [#4316](https://github.com/scrapy/scrapy/issues/4316), [#4318](https://github.com/scrapy/scrapy/issues/4318))
* The new [`Response.follow_all`](../topics/request-response.md)
  method offers the same functionality as
  [`Response.follow`](../topics/request-response.md) but supports an
  iterable of URLs as input and returns an iterable of requests
  ([#2582](https://github.com/scrapy/scrapy/issues/2582), [#4057](https://github.com/scrapy/scrapy/issues/4057), [#4286](https://github.com/scrapy/scrapy/issues/4286))
* [Media pipelines](../topics/media-pipeline.md) now support [FTP
  storage](../topics/media-pipeline.md "FTP server storage") ([#3928](https://github.com/scrapy/scrapy/issues/3928), [#3961](https://github.com/scrapy/scrapy/issues/3961))
* The new [`Response.certificate`](../topics/request-response.md)
  attribute exposes the SSL certificate of the server as a
  [`twisted.internet.ssl.Certificate`](https://docs.twisted.org/en/stable/api/twisted.internet.ssl.Certificate.html) object for HTTPS responses
  ([#2726](https://github.com/scrapy/scrapy/issues/2726), [#4054](https://github.com/scrapy/scrapy/issues/4054))
* A new `DNS_RESOLVER` setting allows enabling IPv6 support
  ([#1031](https://github.com/scrapy/scrapy/issues/1031), [#4227](https://github.com/scrapy/scrapy/issues/4227))
* A new `SCRAPER_SLOT_MAX_ACTIVE_SIZE` setting allows configuring the
  existing soft limit that pauses request downloads when the total response
  data being processed is too high ([#1410](https://github.com/scrapy/scrapy/issues/1410), [#3551](https://github.com/scrapy/scrapy/issues/3551))
* A new `TWISTED_REACTOR` setting allows customizing the
  [`reactor`](https://docs.twisted.org/en/stable/api/twisted.internet.reactor.html) that Scrapy uses, allowing to
  [enable asyncio support](https://docs.scrapy.org/en/latest/topics/asyncio.md) or deal with a
  [common macOS issue](../faq.md "How to deal with <class 'ValueError'>: filedescriptor out of range in select() exceptions?") ([#2905](https://github.com/scrapy/scrapy/issues/2905),
  [#4294](https://github.com/scrapy/scrapy/issues/4294))
* Scheduler disk and memory queues may now use the class methods
  `from_crawler` or `from_settings` ([#3884](https://github.com/scrapy/scrapy/issues/3884))
* The new [`Response.cb_kwargs`](../topics/request-response.md)
  attribute serves as a shortcut for [`Response.request.cb_kwargs`](../topics/request-response.md) ([#4331](https://github.com/scrapy/scrapy/issues/4331))
* [`Response.follow`](../topics/request-response.md) now supports a
  `flags` parameter, for consistency with [`Request`](../topics/request-response.md)
  ([#4277](https://github.com/scrapy/scrapy/issues/4277), [#4279](https://github.com/scrapy/scrapy/issues/4279))
* [Item loader processors](../topics/loaders.md "Input and Output processors") can now be
  regular functions, they no longer need to be methods ([#3899](https://github.com/scrapy/scrapy/issues/3899))
* [`Rule`](../topics/spiders.md) now accepts an `errback` parameter
  ([#4000](https://github.com/scrapy/scrapy/issues/4000))
* [`Request`](../topics/request-response.md) no longer requires a `callback` parameter
  when an `errback` parameter is specified ([#3586](https://github.com/scrapy/scrapy/issues/3586), [#4008](https://github.com/scrapy/scrapy/issues/4008))
* [`LogFormatter`](../topics/logging.md) now supports some additional
  methods:
  * [`download_error`](../topics/logging.md) for
    download errors
  * [`item_error`](../topics/logging.md) for exceptions
    raised during item processing by [item pipelines](../topics/item-pipeline.md)
  * [`spider_error`](../topics/logging.md) for exceptions
    raised from [spider callbacks](../topics/spiders.md)

  ([#374](https://github.com/scrapy/scrapy/issues/374), [#3986](https://github.com/scrapy/scrapy/issues/3986), [#3989](https://github.com/scrapy/scrapy/issues/3989), [#4176](https://github.com/scrapy/scrapy/issues/4176), [#4188](https://github.com/scrapy/scrapy/issues/4188))
* The `FEED_URI` setting now supports [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path) values
  ([#3731](https://github.com/scrapy/scrapy/issues/3731), [#4074](https://github.com/scrapy/scrapy/issues/4074))
* A new [`request_left_downloader`](../topics/signals.md) signal is sent when a request
  leaves the downloader ([#4303](https://github.com/scrapy/scrapy/issues/4303))
* Scrapy logs a warning when it detects a request callback or errback that
  uses `yield` but also returns a value, since the returned value would be
  lost ([#3484](https://github.com/scrapy/scrapy/issues/3484), [#3869](https://github.com/scrapy/scrapy/issues/3869))
* [`Spider`](../topics/spiders.md) objects now raise an `AttributeError`
  exception if they do not have a `start_urls`
  attribute nor reimplement `scrapy.spiders.Spider.start_requests()`,
  but have a `start_url` attribute ([#4133](https://github.com/scrapy/scrapy/issues/4133), [#4170](https://github.com/scrapy/scrapy/issues/4170))
* [`BaseItemExporter`](../topics/exporters.md) subclasses may now use
  `super().__init__(**kwargs)` instead of `self._configure(kwargs)` in
  their `__init__` method, passing `dont_fail=True` to the parent
  `__init__` method if needed, and accessing `kwargs` at `self._kwargs`
  after calling their parent `__init__` method ([#4193](https://github.com/scrapy/scrapy/issues/4193),
  [#4370](https://github.com/scrapy/scrapy/issues/4370))
* A new `keep_fragments` parameter of
  `scrapy.utils.request.request_fingerprint` allows to generate
  different fingerprints for requests with different fragments in their URL
  ([#4104](https://github.com/scrapy/scrapy/issues/4104))
* Download handlers (see [`DOWNLOAD_HANDLERS`](../topics/settings.md)) may now use the
  `from_settings` and `from_crawler` class methods that other Scrapy
  components already supported ([#4126](https://github.com/scrapy/scrapy/issues/4126))
* `scrapy.utils.python.MutableChain.__iter__` now returns `self`,
  allowing it to be used as a sequence.
  ([#4153](https://github.com/scrapy/scrapy/issues/4153))

### Bug fixes

* The [`crawl`](../topics/commands.md) command now also exits with exit code 1 when an
  exception happens before the crawling starts ([#4175](https://github.com/scrapy/scrapy/issues/4175), [#4207](https://github.com/scrapy/scrapy/issues/4207))
* [`LinkExtractor.extract_links`](../topics/link-extractors.md) no longer
  re-encodes the query string or URLs from non-UTF-8 responses in UTF-8
  ([#998](https://github.com/scrapy/scrapy/issues/998), [#1403](https://github.com/scrapy/scrapy/issues/1403), [#1949](https://github.com/scrapy/scrapy/issues/1949), [#4321](https://github.com/scrapy/scrapy/issues/4321))
* The first spider middleware (see [`SPIDER_MIDDLEWARES`](../topics/settings.md)) now also
  processes exceptions raised from callbacks that are generators
  ([#4260](https://github.com/scrapy/scrapy/issues/4260), [#4272](https://github.com/scrapy/scrapy/issues/4272))
* Redirects to URLs starting with 3 slashes (`///`) are now supported
  ([#4032](https://github.com/scrapy/scrapy/issues/4032), [#4042](https://github.com/scrapy/scrapy/issues/4042))
* [`Request`](../topics/request-response.md) no longer accepts strings as `url` simply
  because they have a colon ([#2552](https://github.com/scrapy/scrapy/issues/2552), [#4094](https://github.com/scrapy/scrapy/issues/4094))
* The correct encoding is now used for attach names in
  `MailSender` ([#4229](https://github.com/scrapy/scrapy/issues/4229), [#4239](https://github.com/scrapy/scrapy/issues/4239))
* [`RFPDupeFilter`](../topics/settings.md), the default
  [`DUPEFILTER_CLASS`](../topics/settings.md), no longer writes an extra `\r` character on
  each line in Windows, which made the size of the `requests.seen` file
  unnecessarily large on that platform ([#4283](https://github.com/scrapy/scrapy/issues/4283))
* Z shell auto-completion now looks for `.html` files, not `.http` files,
  and covers the `-h` command-line switch ([#4122](https://github.com/scrapy/scrapy/issues/4122), [#4291](https://github.com/scrapy/scrapy/issues/4291))
* Adding items to a `scrapy.utils.datatypes.LocalCache` object
  without a `limit` defined no longer raises a `TypeError` exception
  ([#4123](https://github.com/scrapy/scrapy/issues/4123))
* Fixed a typo in the message of the `ValueError` exception raised when
  `scrapy.utils.misc.create_instance()` gets both `settings` and
  `crawler` set to `None` ([#4128](https://github.com/scrapy/scrapy/issues/4128))

### Documentation

* API documentation now links to an online, syntax-highlighted view of the
  corresponding source code ([#4148](https://github.com/scrapy/scrapy/issues/4148))
* Links to unexisting documentation pages now allow access to the sidebar
  ([#4152](https://github.com/scrapy/scrapy/issues/4152), [#4169](https://github.com/scrapy/scrapy/issues/4169))
* Cross-references within our documentation now display a tooltip when
  hovered ([#4173](https://github.com/scrapy/scrapy/issues/4173), [#4183](https://github.com/scrapy/scrapy/issues/4183))
* Improved the documentation about [`LinkExtractor.extract_links`](../topics/link-extractors.md) and
  simplified [Link Extractors](../topics/link-extractors.md) ([#4045](https://github.com/scrapy/scrapy/issues/4045))
* Clarified how [`ItemLoader.item`](../topics/loaders.md)
  works ([#3574](https://github.com/scrapy/scrapy/issues/3574), [#4099](https://github.com/scrapy/scrapy/issues/4099))
* Clarified that [`logging.basicConfig()`](https://docs.python.org/3/library/logging.html#logging.basicConfig) should not be used when also
  using [`CrawlerProcess`](../topics/api.md) ([#2149](https://github.com/scrapy/scrapy/issues/2149),
  [#2352](https://github.com/scrapy/scrapy/issues/2352), [#3146](https://github.com/scrapy/scrapy/issues/3146), [#3960](https://github.com/scrapy/scrapy/issues/3960))
* Clarified the requirements for [`Request`](../topics/request-response.md) objects
  [when using persistence](../topics/jobs.md "Request serialization") ([#4124](https://github.com/scrapy/scrapy/issues/4124),
  [#4139](https://github.com/scrapy/scrapy/issues/4139))
* Clarified how to install a [custom image pipeline](../topics/media-pipeline.md "Custom Images pipeline example") ([#4034](https://github.com/scrapy/scrapy/issues/4034), [#4252](https://github.com/scrapy/scrapy/issues/4252))
* Fixed the signatures of the `file_path` method in [media pipeline](../topics/media-pipeline.md) examples ([#4290](https://github.com/scrapy/scrapy/issues/4290))
* Covered a backward-incompatible change in Scrapy 1.7.0 affecting custom
  [`scrapy.core.scheduler.Scheduler`](../topics/scheduler.md) subclasses ([#4274](https://github.com/scrapy/scrapy/issues/4274))
* Improved the `README.rst` and `CODE_OF_CONDUCT.md` files
  ([#4059](https://github.com/scrapy/scrapy/issues/4059))
* Documentation examples are now checked as part of our test suite and we
  have fixed some of the issues detected ([#4142](https://github.com/scrapy/scrapy/issues/4142), [#4146](https://github.com/scrapy/scrapy/issues/4146),
  [#4171](https://github.com/scrapy/scrapy/issues/4171), [#4184](https://github.com/scrapy/scrapy/issues/4184), [#4190](https://github.com/scrapy/scrapy/issues/4190))
* Fixed logic issues, broken links and typos ([#4247](https://github.com/scrapy/scrapy/issues/4247), [#4258](https://github.com/scrapy/scrapy/issues/4258),
  [#4282](https://github.com/scrapy/scrapy/issues/4282), [#4288](https://github.com/scrapy/scrapy/issues/4288), [#4305](https://github.com/scrapy/scrapy/issues/4305), [#4308](https://github.com/scrapy/scrapy/issues/4308), [#4323](https://github.com/scrapy/scrapy/issues/4323),
  [#4338](https://github.com/scrapy/scrapy/issues/4338), [#4359](https://github.com/scrapy/scrapy/issues/4359), [#4361](https://github.com/scrapy/scrapy/issues/4361))
* Improved consistency when referring to the `__init__` method of an object
  ([#4086](https://github.com/scrapy/scrapy/issues/4086), [#4088](https://github.com/scrapy/scrapy/issues/4088))
* Fixed an inconsistency between code and output in [Scrapy at a glance](../intro/overview.md)
  ([#4213](https://github.com/scrapy/scrapy/issues/4213))
* Extended [`intersphinx`](https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html#module-sphinx.ext.intersphinx) usage ([#4147](https://github.com/scrapy/scrapy/issues/4147),
  [#4172](https://github.com/scrapy/scrapy/issues/4172), [#4185](https://github.com/scrapy/scrapy/issues/4185), [#4194](https://github.com/scrapy/scrapy/issues/4194), [#4197](https://github.com/scrapy/scrapy/issues/4197))
* We now use a recent version of Python to build the documentation
  ([#4140](https://github.com/scrapy/scrapy/issues/4140), [#4249](https://github.com/scrapy/scrapy/issues/4249))
* Cleaned up documentation ([#4143](https://github.com/scrapy/scrapy/issues/4143), [#4275](https://github.com/scrapy/scrapy/issues/4275))

### Quality assurance

* Re-enabled proxy `CONNECT` tests ([#2545](https://github.com/scrapy/scrapy/issues/2545), [#4114](https://github.com/scrapy/scrapy/issues/4114))
* Added [Bandit](https://bandit.readthedocs.io/en/latest/) security checks to our test suite ([#4162](https://github.com/scrapy/scrapy/issues/4162),
  [#4181](https://github.com/scrapy/scrapy/issues/4181))
* Added [Flake8](https://flake8.pycqa.org/en/latest/) style checks to our test suite and applied many of the
  corresponding changes ([#3944](https://github.com/scrapy/scrapy/issues/3944), [#3945](https://github.com/scrapy/scrapy/issues/3945), [#4137](https://github.com/scrapy/scrapy/issues/4137),
  [#4157](https://github.com/scrapy/scrapy/issues/4157), [#4167](https://github.com/scrapy/scrapy/issues/4167), [#4174](https://github.com/scrapy/scrapy/issues/4174), [#4186](https://github.com/scrapy/scrapy/issues/4186), [#4195](https://github.com/scrapy/scrapy/issues/4195),
  [#4238](https://github.com/scrapy/scrapy/issues/4238), [#4246](https://github.com/scrapy/scrapy/issues/4246), [#4355](https://github.com/scrapy/scrapy/issues/4355), [#4360](https://github.com/scrapy/scrapy/issues/4360), [#4365](https://github.com/scrapy/scrapy/issues/4365))
* Improved test coverage ([#4097](https://github.com/scrapy/scrapy/issues/4097), [#4218](https://github.com/scrapy/scrapy/issues/4218), [#4236](https://github.com/scrapy/scrapy/issues/4236))
* Started reporting slowest tests, and improved the performance of some of
  them ([#4163](https://github.com/scrapy/scrapy/issues/4163), [#4164](https://github.com/scrapy/scrapy/issues/4164))
* Fixed broken tests and refactored some tests ([#4014](https://github.com/scrapy/scrapy/issues/4014), [#4095](https://github.com/scrapy/scrapy/issues/4095),
  [#4244](https://github.com/scrapy/scrapy/issues/4244), [#4268](https://github.com/scrapy/scrapy/issues/4268), [#4372](https://github.com/scrapy/scrapy/issues/4372))
* Modified the [tox](https://tox.wiki/en/latest/index.html) configuration to allow running tests
  with any Python version, run [Bandit](https://bandit.readthedocs.io/en/latest/) and [Flake8](https://flake8.pycqa.org/en/latest/) tests by default, and
  enforce a minimum tox version programmatically ([#4179](https://github.com/scrapy/scrapy/issues/4179))
* Cleaned up code ([#3937](https://github.com/scrapy/scrapy/issues/3937), [#4208](https://github.com/scrapy/scrapy/issues/4208), [#4209](https://github.com/scrapy/scrapy/issues/4209),
  [#4210](https://github.com/scrapy/scrapy/issues/4210), [#4212](https://github.com/scrapy/scrapy/issues/4212), [#4369](https://github.com/scrapy/scrapy/issues/4369), [#4376](https://github.com/scrapy/scrapy/issues/4376), [#4378](https://github.com/scrapy/scrapy/issues/4378))

### Changes to scheduler queue classes

The following changes may impact any custom queue classes of all types:

* The `push` method no longer receives a second positional parameter
  containing `request.priority * -1`. If you need that value, get it
  from the first positional parameter, `request`, instead, or use
  the new `priority()`
  method in `scrapy.core.scheduler.ScrapyPriorityQueue`
  subclasses.

The following changes may impact custom priority queue classes:

* In the `__init__` method or the `from_crawler` or `from_settings`
  class methods:
  * The parameter that used to contain a factory function,
    `qfactory`, is now passed as a keyword parameter named
    `downstream_queue_cls`.
  * A new keyword parameter has been added: `key`. It is a string
    that is always an empty string for memory queues and indicates the
    [`JOBDIR`](../topics/settings.md) value for disk queues.
  * The parameter for disk queues that contains data from the previous
    crawl, `startprios` or `slot_startprios`, is now passed as a
    keyword parameter named `startprios`.
  * The `serialize` parameter is no longer passed. The disk queue
    class must take care of request serialization on its own before
    writing to disk, using the
    `request_to_dict()` and
    `request_from_dict()` functions from the
    `scrapy.utils.reqser` module.

The following changes may impact custom disk and memory queue classes:

* The signature of the `__init__` method is now
  `__init__(self, crawler, key)`.

The following changes affect specifically the
`ScrapyPriorityQueue` and
`DownloaderAwarePriorityQueue` classes from
[`scrapy.core.scheduler`](../topics/scheduler.md) and may affect subclasses:

* In the `__init__` method, most of the changes described above apply.

  `__init__` may still receive all parameters as positional parameters,
  however:
  * `downstream_queue_cls`, which replaced `qfactory`, must be
    instantiated differently.

    `qfactory` was instantiated with a priority value (integer).

    Instances of `downstream_queue_cls` should be created using
    the new
    `ScrapyPriorityQueue.qfactory`
    or
    `DownloaderAwarePriorityQueue.pqfactory`
    methods.
  * The new `key` parameter displaced the `startprios`
    parameter 1 position to the right.
* The following class attributes have been added:
  * `crawler`
  * `downstream_queue_cls`
    (details above)
  * `key` (details above)
* The `serialize` attribute has been removed (details above)

The following changes affect specifically the
`ScrapyPriorityQueue` class and may affect
subclasses:

* A new `priority()`
  method has been added which, given a request, returns
  `request.priority * -1`.

  It is used in `push()`
  to make up for the removal of its `priority` parameter.
* The `spider` attribute has been removed. Use
  `crawler.spider`
  instead.

The following changes affect specifically the
`DownloaderAwarePriorityQueue` class and may
affect subclasses:

* A new `pqueues`
  attribute offers a mapping of downloader slot names to the
  corresponding instances of
  `downstream_queue_cls`.

([#3884](https://github.com/scrapy/scrapy/issues/3884))
